This tool is designed to merge translation files (pot files) for internationalization (i18n) in JavaScript projects. It is particularly useful when working with multiple contributors or maintaining translations across various versions of your project.
-
Merge Blocks: The tool merges translation blocks that have matching
msgid
values. It intelligently combines translator comments and references, ensuring that valuable context is retained. -
Handling Duplicates: Duplicate translator comments are not added to the merged block. The tool maintains uniqueness in the merged set.
-
Flexible Merging: Blocks are merged when the
msgid
values match, and eithermsgctx
ormsgstr
is empty for one of the blocks. This flexibility allows merging blocks with different context or translations.
-
Install Node.js: Make sure you have Node.js installed on your machine. You can download it from https://nodejs.org/.
-
Clone the Repository: Clone this repository to your local machine using the following command:
git clone https://github.com/erikyo/gettext-merger.git
- Install Dependencies: Navigate to the project directory and install the required dependencies.
cd gettext-merger
npm install
## optionally if you want to use the CLI to test the library
npm link
The tool can be used either as a library in your Node.js project or as a command-line tool.
npx gettext-merger -i tests/fixtures/file1.pot tests/fixtures/file2.pot -o tests/fixtures/potfile.pot
import { mergePotFile } from 'gettext-merger';
const filePaths = ['file1.pot', 'file2.pot'];
const [headers, mergedSet] = await mergePotFile(filePaths);
import { mergePotFileContent } from 'gettext-merger';
const fileContents = [
`msgid "Product Status"
msgstr "Field: Useless Product Status"
#. Chunk file for editing product page
#: assets/client/admin/chunks/edit-product-page.js:1
msgid "Save Changes"
msgstr "Button: Save Useless Changes"`,
`#. Field in products widget class
#: includes/widgets/class-wc-widget-products.php:53
msgid "Widget Title"
msgstr "Field: Useless Widget Title"`
];
const mergedContent = mergePotFileContent(fileContents);
import { mergePotObject } from 'gettext-merger';
const setOfBlocksArray = [{
msgid: 'text1',
comments: {
extracted: ['#. Translator comment'],
reference: ['#: app.js'],
},
},{
msgid: 'text2',
comments: {
extracted: ['#. Translator comment'],
reference: ['#: app.js'],
},
}];
const mergedSet = mergePotObject(setOfBlocksArray);
import { extractPotHeader, Block } from 'gettext-merger';
const potFileContent = [`# Copyright (C) 2024 FantasyTech
# This file is distributed under the same license as the Unicorn Plugin.
msgid ""
msgstr ""
"Project-Id-Version: Project Name\n"
msgid "Hello"
msgstr "Hola"
msgid "Goodbye"
msgstr "Adiós"`];
const [header, remainingContent] = extractPotHeader(potFileContent);
The Block
class represents a single block of a PO file.
msgid?: string
: The main message string.msgstr?: string[]
: An array of translated strings.msgid_plural?: string
: The plural form of the main message.msgctxt?: string
: Context for the message.comments?: GetTextComment
: Comments associated with the block.
-
Constructor(data: string | string[] | Partial): Initializes a new instance of the
Block
class.data
: The data to initialize the block with, which can be a string, an array of strings, or a partial block object.
-
parseBlock(lines: string[]): Block | undefined: Parses the provided lines and populates the block's properties.
-
toStr(): string: Converts the block to a string representation.
-
toJson(): GetTextTranslation: Converts the block to a JSON representation compatible with gettext-parser.
-
hash(): number: Generates a hash value based on the concatenation of msgctxt and msgid.
-
merge(other: Block): Merges another block with the current block.
import { Block } from 'gettext-merger'
// Create a new block
const block1 = new Block('msgid "example"')
// Access and modify block properties
block1.msgstr = ['translated example']
// Convert the block to a string representation
console.log(block1.toStr())
// Merge two blocks
const block2 = new Block('msgid "example"')
block2.msgstr = ['another translated example']
block1.merge(block2)
// Output the merged block
console.log(block1.toStr())
The SetOfBlocks
class represents a collection of Block
objects.
blocks: Block[]
: An array ofBlock
objects contained in the set.path?: string
: Optional path to the file associated with the set.
-
Constructor(arr?: Block[], path?: string): Initializes a new instance of the
SetOfBlocks
class.arr
: Optional array ofBlock
objects to initialize the set with.path
: Optional path to the file associated with the set.
-
add(block: Block): void: Adds a block to the collection, merging if a duplicate exists.
-
getDuplicate(hash: number): Block | undefined: Finds and returns a duplicate block based on the given hash.
-
toStr(): string: Converts the blocks in the set to a string representation.
-
toJson(): GetTextTranslations['translations']: Converts the blocks in the set to a JSON representation compatible with the gettext-parser module.
-
addArray(arr: Block[]): void: Adds an array of
Block
objects to the current instance.
import { SetOfBlocks, Block } from 'gettext-merger'
// Create a new set of blocks
const blockSet = new SetOfBlocks()
// Create a new block
const block1 = new Block('msgid "example"')
// Add the block to the set
blockSet.add(block1)
// Convert the set to a string representation
console.log(blockSet.toStr())
// Add an array of blocks to the set
const block2 = new Block('msgid "another example"')
blockSet.addArray([block2])
// Output the JSON representation of the set
console.log(blockSet.toJson())
Run tests using the following command:
npm test
If you find any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request.
This tool is licensed under the GNU General Public License v3.