@intlayer/sync-po-plugin 9.0.0-canary.17 → 9.0.0-canary.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/loadPO.cjs.map +1 -1
- package/dist/cjs/poFormat.cjs.map +1 -1
- package/dist/cjs/syncPO.cjs.map +1 -1
- package/dist/esm/loadPO.mjs.map +1 -1
- package/dist/esm/poFormat.mjs.map +1 -1
- package/dist/esm/syncPO.mjs.map +1 -1
- package/dist/types/loadPO.d.ts +0 -1
- package/dist/types/loadPO.d.ts.map +1 -1
- package/dist/types/poFormat.d.ts +0 -1
- package/dist/types/poFormat.d.ts.map +1 -1
- package/dist/types/syncPO.d.ts +0 -1
- package/dist/types/syncPO.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/cjs/loadPO.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadPO.cjs","names":["poCodec"],"sources":["../../src/loadPO.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\nexport type LoadPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadPO({\n * source: ({ key }) => `./resources/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Read-only PO ingestion plugin: loads gettext PO files as dictionaries\n * without ever writing back to them.\n */\nexport const loadPO = (options: LoadPOPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; never split on first level.\n splitKeys: false,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;;AAwEA,MAAa,UAAU,iEACJ;CACf,MAAM;CACN,+DAA2B;EACzB,QAAQ,QAAQ;EAChB,OAAOA;EACP,WAAW;
|
|
1
|
+
{"version":3,"file":"loadPO.cjs","names":["poCodec"],"sources":["../../src/loadPO.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\nexport type LoadPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadPO({\n * source: ({ key }) => `./resources/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Read-only PO ingestion plugin: loads gettext PO files as dictionaries\n * without ever writing back to them.\n */\nexport const loadPO = (options: LoadPOPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; never split on first level.\n splitKeys: false,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;;AAwEA,MAAa,UAAU,iEACJ;CACf,MAAM;CACN,+DAA2B;EACzB,QAAQ,QAAQ;EAChB,OAAOA;EACP,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ;CAER,WAAW;CACX,gBAAgB,QAAQ;AAC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poFormat.cjs","names":[],"sources":["../../src/poFormat.ts"],"sourcesContent":["import type { FormatCodec } from '@intlayer/engine/syncPluginKit';\n\nconst unescapePO = (str: string): string =>\n str\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n\nconst escapePO = (str: string): string =>\n str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n\n/**\n * Parse a PO file string into a flat msgid → msgstr record.\n * Skips the PO header (msgid \"\"), comment lines, and plural/context keywords.\n */\nexport const parsePO = (fileContent: string): Record<string, string> => {\n const result: Record<string, string> = {};\n const lines = fileContent\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .split('\\n');\n\n let msgid = '';\n let msgstr = '';\n let currentField: 'msgid' | 'msgstr' | null = null;\n\n const finalize = () => {\n if (msgid !== '') {\n result[msgid] = msgstr;\n }\n msgid = '';\n msgstr = '';\n currentField = null;\n };\n\n for (const line of lines) {\n // Skip all comment types (#, #., #:, #,, #|)\n if (line.startsWith('#')) continue;\n\n if (line.trim() === '') {\n finalize();\n continue;\n }\n\n const msgidMatch = line.match(/^msgid\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgidMatch?.[1]) {\n // Starting a new entry — finalize the previous one first\n finalize();\n msgid = unescapePO(msgidMatch[1]);\n currentField = 'msgid';\n continue;\n }\n\n const msgstrMatch = line.match(/^msgstr\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgstrMatch?.[1]) {\n msgstr = unescapePO(msgstrMatch[1]);\n currentField = 'msgstr';\n continue;\n }\n\n // Continuation line: `\"...\"` appends to the current keyword's value\n const contMatch = line.match(/^\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (contMatch?.[1]) {\n if (currentField === 'msgid') {\n msgid += unescapePO(contMatch[1]);\n } else if (currentField === 'msgstr') {\n msgstr += unescapePO(contMatch[1]);\n }\n continue;\n }\n\n // Other keywords (msgid_plural, msgstr[n], msgctxt) — not supported; reset field\n currentField = null;\n }\n\n // Finalize the last entry in the file (no trailing blank line needed)\n finalize();\n\n return result;\n};\n\n/**\n * Serialize a flat key → value record to PO file format.\n * Non-string values are silently skipped.\n */\nexport const serializePO = (\n content: Record<string, unknown>,\n locale?: string\n): string => {\n const lines: string[] = [];\n\n // PO header entry\n lines.push('msgid \"\"');\n lines.push('msgstr \"\"');\n lines.push('\"Content-Type: text/plain; charset=UTF-8\\\\n\"');\n lines.push('\"Content-Transfer-Encoding: 8bit\\\\n\"');\n if (locale) {\n lines.push(`\"Language: ${locale}\\\\n\"`);\n }\n lines.push('\"MIME-Version: 1.0\\\\n\"');\n lines.push('');\n\n for (const [msgid, msgstr] of Object.entries(content)) {\n if (typeof msgstr !== 'string') continue;\n\n lines.push(`msgid \"${escapePO(msgid)}\"`);\n lines.push(`msgstr \"${escapePO(msgstr)}\"`);\n lines.push('');\n }\n\n return `${lines.join('\\n')}\\n`;\n};\n\n/**\n * PO payload codec bridging {@link parsePO} / {@link serializePO} to the\n * sync-plugin kit.\n */\nexport const poCodec: FormatCodec = {\n parse: parsePO,\n serialize: (content, { locale }) => serializePO(content, locale),\n};\n"],"mappings":";;;AAEA,MAAM,cAAc,QAClB,IACG,QAAQ,QAAQ,
|
|
1
|
+
{"version":3,"file":"poFormat.cjs","names":[],"sources":["../../src/poFormat.ts"],"sourcesContent":["import type { FormatCodec } from '@intlayer/engine/syncPluginKit';\n\nconst unescapePO = (str: string): string =>\n str\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n\nconst escapePO = (str: string): string =>\n str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n\n/**\n * Parse a PO file string into a flat msgid → msgstr record.\n * Skips the PO header (msgid \"\"), comment lines, and plural/context keywords.\n */\nexport const parsePO = (fileContent: string): Record<string, string> => {\n const result: Record<string, string> = {};\n const lines = fileContent\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .split('\\n');\n\n let msgid = '';\n let msgstr = '';\n let currentField: 'msgid' | 'msgstr' | null = null;\n\n const finalize = () => {\n if (msgid !== '') {\n result[msgid] = msgstr;\n }\n msgid = '';\n msgstr = '';\n currentField = null;\n };\n\n for (const line of lines) {\n // Skip all comment types (#, #., #:, #,, #|)\n if (line.startsWith('#')) continue;\n\n if (line.trim() === '') {\n finalize();\n continue;\n }\n\n const msgidMatch = line.match(/^msgid\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgidMatch?.[1]) {\n // Starting a new entry — finalize the previous one first\n finalize();\n msgid = unescapePO(msgidMatch[1]);\n currentField = 'msgid';\n continue;\n }\n\n const msgstrMatch = line.match(/^msgstr\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgstrMatch?.[1]) {\n msgstr = unescapePO(msgstrMatch[1]);\n currentField = 'msgstr';\n continue;\n }\n\n // Continuation line: `\"...\"` appends to the current keyword's value\n const contMatch = line.match(/^\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (contMatch?.[1]) {\n if (currentField === 'msgid') {\n msgid += unescapePO(contMatch[1]);\n } else if (currentField === 'msgstr') {\n msgstr += unescapePO(contMatch[1]);\n }\n continue;\n }\n\n // Other keywords (msgid_plural, msgstr[n], msgctxt) — not supported; reset field\n currentField = null;\n }\n\n // Finalize the last entry in the file (no trailing blank line needed)\n finalize();\n\n return result;\n};\n\n/**\n * Serialize a flat key → value record to PO file format.\n * Non-string values are silently skipped.\n */\nexport const serializePO = (\n content: Record<string, unknown>,\n locale?: string\n): string => {\n const lines: string[] = [];\n\n // PO header entry\n lines.push('msgid \"\"');\n lines.push('msgstr \"\"');\n lines.push('\"Content-Type: text/plain; charset=UTF-8\\\\n\"');\n lines.push('\"Content-Transfer-Encoding: 8bit\\\\n\"');\n if (locale) {\n lines.push(`\"Language: ${locale}\\\\n\"`);\n }\n lines.push('\"MIME-Version: 1.0\\\\n\"');\n lines.push('');\n\n for (const [msgid, msgstr] of Object.entries(content)) {\n if (typeof msgstr !== 'string') continue;\n\n lines.push(`msgid \"${escapePO(msgid)}\"`);\n lines.push(`msgstr \"${escapePO(msgstr)}\"`);\n lines.push('');\n }\n\n return `${lines.join('\\n')}\\n`;\n};\n\n/**\n * PO payload codec bridging {@link parsePO} / {@link serializePO} to the\n * sync-plugin kit.\n */\nexport const poCodec: FormatCodec = {\n parse: parsePO,\n serialize: (content, { locale }) => serializePO(content, locale),\n};\n"],"mappings":";;;AAEA,MAAM,cAAc,QAClB,IACG,QAAQ,QAAQ,IAAI,CAAC,CACrB,QAAQ,QAAQ,GAAI,CAAC,CACrB,QAAQ,QAAQ,IAAI,CAAC,CACrB,QAAQ,QAAQ,IAAG,CAAC,CACpB,QAAQ,SAAS,IAAI;AAE1B,MAAM,YAAY,QAChB,IACG,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,MAAM,MAAK,CAAC,CACpB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,OAAO,KAAK;;;;;AAMzB,MAAa,WAAW,gBAAgD;CACtE,MAAM,SAAiC,CAAC;CACxC,MAAM,QAAQ,YACX,QAAQ,SAAS,IAAI,CAAC,CACtB,QAAQ,OAAO,IAAI,CAAC,CACpB,MAAM,IAAI;CAEb,IAAI,QAAQ;CACZ,IAAI,SAAS;CACb,IAAI,eAA0C;CAE9C,MAAM,iBAAiB;EACrB,IAAI,UAAU,IACZ,OAAO,SAAS;EAElB,QAAQ;EACR,SAAS;EACT,eAAe;CACjB;CAEA,KAAK,MAAM,QAAQ,OAAO;EAExB,IAAI,KAAK,WAAW,GAAG,GAAG;EAE1B,IAAI,KAAK,KAAK,MAAM,IAAI;GACtB,SAAS;GACT;EACF;EAEA,MAAM,aAAa,KAAK,MAAM,+BAA+B;EAC7D,IAAI,aAAa,IAAI;GAEnB,SAAS;GACT,QAAQ,WAAW,WAAW,EAAE;GAChC,eAAe;GACf;EACF;EAEA,MAAM,cAAc,KAAK,MAAM,gCAAgC;EAC/D,IAAI,cAAc,IAAI;GACpB,SAAS,WAAW,YAAY,EAAE;GAClC,eAAe;GACf;EACF;EAGA,MAAM,YAAY,KAAK,MAAM,uBAAuB;EACpD,IAAI,YAAY,IAAI;GAClB,IAAI,iBAAiB,SACnB,SAAS,WAAW,UAAU,EAAE;QAC3B,IAAI,iBAAiB,UAC1B,UAAU,WAAW,UAAU,EAAE;GAEnC;EACF;EAGA,eAAe;CACjB;CAGA,SAAS;CAET,OAAO;AACT;;;;;AAMA,MAAa,eACX,SACA,WACW;CACX,MAAM,QAAkB,CAAC;CAGzB,MAAM,KAAK,YAAU;CACrB,MAAM,KAAK,aAAW;CACtB,MAAM,KAAK,gDAA8C;CACzD,MAAM,KAAK,wCAAsC;CACjD,IAAI,QACF,MAAM,KAAK,cAAc,OAAO,KAAK;CAEvC,MAAM,KAAK,0BAAwB;CACnC,MAAM,KAAK,EAAE;CAEb,KAAK,MAAM,CAAC,OAAO,WAAW,OAAO,QAAQ,OAAO,GAAG;EACrD,IAAI,OAAO,WAAW,UAAU;EAEhC,MAAM,KAAK,UAAU,SAAS,KAAK,EAAE,EAAE;EACvC,MAAM,KAAK,WAAW,SAAS,MAAM,EAAE,EAAE;EACzC,MAAM,KAAK,EAAE;CACf;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;;;;;AAMA,MAAa,UAAuB;CAClC,OAAO;CACP,YAAY,SAAS,EAAE,aAAa,YAAY,SAAS,MAAM;AACjE"}
|
package/dist/cjs/syncPO.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPO.cjs","names":["poCodec"],"sources":["../../src/syncPO.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { DictionaryLocation } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\n// Re-exported for backward compatibility: these helpers used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\nexport { parsePO, serializePO } from './poFormat';\n\nexport type SyncPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncPO({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.po`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncPO({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Two-way PO synchronization plugin: ingests gettext PO files as dictionaries\n * and writes the merged build output back to the same files.\n */\nexport const syncPO = async (options: SyncPOPluginOptions): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-po::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; there is no namespace level\n // to split on, regardless of the source pattern shape.\n splitKeys: false,\n });\n};\n"],"mappings":";;;;;;;;;;AA8DA,MAAa,SAAS,OAAO,YAAkD;CAM7E,MAAM,kBAAkB,YAAY,uDAHlC,QAAQ,wEACoB,WAAW,
|
|
1
|
+
{"version":3,"file":"syncPO.cjs","names":["poCodec"],"sources":["../../src/syncPO.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { DictionaryLocation } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\n// Re-exported for backward compatibility: these helpers used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\nexport { parsePO, serializePO } from './poFormat';\n\nexport type SyncPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncPO({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.po`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncPO({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Two-way PO synchronization plugin: ingests gettext PO files as dictionaries\n * and writes the merged build output back to the same files.\n */\nexport const syncPO = async (options: SyncPOPluginOptions): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-po::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; there is no namespace level\n // to split on, regardless of the source pattern shape.\n splitKeys: false,\n });\n};\n"],"mappings":";;;;;;;;;;AA8DA,MAAa,SAAS,OAAO,YAAkD;CAM7E,MAAM,kBAAkB,YAAY,uDAHlC,QAAQ,wEACoB,WAAW,YAAY,CACrD;CAGA,4DAAwB;EACtB,MAAM;EACN,+DAA2B;GACzB,QAAQ,QAAQ;GAChB,OAAOA;GACP,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ;EAGR,WAAW;CACb,CAAC;AACH"}
|
package/dist/esm/loadPO.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadPO.mjs","names":[],"sources":["../../src/loadPO.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\nexport type LoadPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadPO({\n * source: ({ key }) => `./resources/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Read-only PO ingestion plugin: loads gettext PO files as dictionaries\n * without ever writing back to them.\n */\nexport const loadPO = (options: LoadPOPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; never split on first level.\n splitKeys: false,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;AAwEA,MAAa,UAAU,YACrB,iBAAiB;CACf,MAAM;CACN,SAAS,kBAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAO;EACP,WAAW;
|
|
1
|
+
{"version":3,"file":"loadPO.mjs","names":[],"sources":["../../src/loadPO.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\nexport type LoadPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadPO({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.po`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadPO({\n * source: ({ key }) => `./resources/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Read-only PO ingestion plugin: loads gettext PO files as dictionaries\n * without ever writing back to them.\n */\nexport const loadPO = (options: LoadPOPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; never split on first level.\n splitKeys: false,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;AAwEA,MAAa,UAAU,YACrB,iBAAiB;CACf,MAAM;CACN,SAAS,kBAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAO;EACP,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ;CAER,WAAW;CACX,gBAAgB,QAAQ;AAC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poFormat.mjs","names":[],"sources":["../../src/poFormat.ts"],"sourcesContent":["import type { FormatCodec } from '@intlayer/engine/syncPluginKit';\n\nconst unescapePO = (str: string): string =>\n str\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n\nconst escapePO = (str: string): string =>\n str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n\n/**\n * Parse a PO file string into a flat msgid → msgstr record.\n * Skips the PO header (msgid \"\"), comment lines, and plural/context keywords.\n */\nexport const parsePO = (fileContent: string): Record<string, string> => {\n const result: Record<string, string> = {};\n const lines = fileContent\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .split('\\n');\n\n let msgid = '';\n let msgstr = '';\n let currentField: 'msgid' | 'msgstr' | null = null;\n\n const finalize = () => {\n if (msgid !== '') {\n result[msgid] = msgstr;\n }\n msgid = '';\n msgstr = '';\n currentField = null;\n };\n\n for (const line of lines) {\n // Skip all comment types (#, #., #:, #,, #|)\n if (line.startsWith('#')) continue;\n\n if (line.trim() === '') {\n finalize();\n continue;\n }\n\n const msgidMatch = line.match(/^msgid\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgidMatch?.[1]) {\n // Starting a new entry — finalize the previous one first\n finalize();\n msgid = unescapePO(msgidMatch[1]);\n currentField = 'msgid';\n continue;\n }\n\n const msgstrMatch = line.match(/^msgstr\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgstrMatch?.[1]) {\n msgstr = unescapePO(msgstrMatch[1]);\n currentField = 'msgstr';\n continue;\n }\n\n // Continuation line: `\"...\"` appends to the current keyword's value\n const contMatch = line.match(/^\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (contMatch?.[1]) {\n if (currentField === 'msgid') {\n msgid += unescapePO(contMatch[1]);\n } else if (currentField === 'msgstr') {\n msgstr += unescapePO(contMatch[1]);\n }\n continue;\n }\n\n // Other keywords (msgid_plural, msgstr[n], msgctxt) — not supported; reset field\n currentField = null;\n }\n\n // Finalize the last entry in the file (no trailing blank line needed)\n finalize();\n\n return result;\n};\n\n/**\n * Serialize a flat key → value record to PO file format.\n * Non-string values are silently skipped.\n */\nexport const serializePO = (\n content: Record<string, unknown>,\n locale?: string\n): string => {\n const lines: string[] = [];\n\n // PO header entry\n lines.push('msgid \"\"');\n lines.push('msgstr \"\"');\n lines.push('\"Content-Type: text/plain; charset=UTF-8\\\\n\"');\n lines.push('\"Content-Transfer-Encoding: 8bit\\\\n\"');\n if (locale) {\n lines.push(`\"Language: ${locale}\\\\n\"`);\n }\n lines.push('\"MIME-Version: 1.0\\\\n\"');\n lines.push('');\n\n for (const [msgid, msgstr] of Object.entries(content)) {\n if (typeof msgstr !== 'string') continue;\n\n lines.push(`msgid \"${escapePO(msgid)}\"`);\n lines.push(`msgstr \"${escapePO(msgstr)}\"`);\n lines.push('');\n }\n\n return `${lines.join('\\n')}\\n`;\n};\n\n/**\n * PO payload codec bridging {@link parsePO} / {@link serializePO} to the\n * sync-plugin kit.\n */\nexport const poCodec: FormatCodec = {\n parse: parsePO,\n serialize: (content, { locale }) => serializePO(content, locale),\n};\n"],"mappings":";AAEA,MAAM,cAAc,QAClB,IACG,QAAQ,QAAQ,
|
|
1
|
+
{"version":3,"file":"poFormat.mjs","names":[],"sources":["../../src/poFormat.ts"],"sourcesContent":["import type { FormatCodec } from '@intlayer/engine/syncPluginKit';\n\nconst unescapePO = (str: string): string =>\n str\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n\nconst escapePO = (str: string): string =>\n str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n\n/**\n * Parse a PO file string into a flat msgid → msgstr record.\n * Skips the PO header (msgid \"\"), comment lines, and plural/context keywords.\n */\nexport const parsePO = (fileContent: string): Record<string, string> => {\n const result: Record<string, string> = {};\n const lines = fileContent\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n')\n .split('\\n');\n\n let msgid = '';\n let msgstr = '';\n let currentField: 'msgid' | 'msgstr' | null = null;\n\n const finalize = () => {\n if (msgid !== '') {\n result[msgid] = msgstr;\n }\n msgid = '';\n msgstr = '';\n currentField = null;\n };\n\n for (const line of lines) {\n // Skip all comment types (#, #., #:, #,, #|)\n if (line.startsWith('#')) continue;\n\n if (line.trim() === '') {\n finalize();\n continue;\n }\n\n const msgidMatch = line.match(/^msgid\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgidMatch?.[1]) {\n // Starting a new entry — finalize the previous one first\n finalize();\n msgid = unescapePO(msgidMatch[1]);\n currentField = 'msgid';\n continue;\n }\n\n const msgstrMatch = line.match(/^msgstr\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (msgstrMatch?.[1]) {\n msgstr = unescapePO(msgstrMatch[1]);\n currentField = 'msgstr';\n continue;\n }\n\n // Continuation line: `\"...\"` appends to the current keyword's value\n const contMatch = line.match(/^\"((?:[^\"\\\\]|\\\\.)*)\"$/);\n if (contMatch?.[1]) {\n if (currentField === 'msgid') {\n msgid += unescapePO(contMatch[1]);\n } else if (currentField === 'msgstr') {\n msgstr += unescapePO(contMatch[1]);\n }\n continue;\n }\n\n // Other keywords (msgid_plural, msgstr[n], msgctxt) — not supported; reset field\n currentField = null;\n }\n\n // Finalize the last entry in the file (no trailing blank line needed)\n finalize();\n\n return result;\n};\n\n/**\n * Serialize a flat key → value record to PO file format.\n * Non-string values are silently skipped.\n */\nexport const serializePO = (\n content: Record<string, unknown>,\n locale?: string\n): string => {\n const lines: string[] = [];\n\n // PO header entry\n lines.push('msgid \"\"');\n lines.push('msgstr \"\"');\n lines.push('\"Content-Type: text/plain; charset=UTF-8\\\\n\"');\n lines.push('\"Content-Transfer-Encoding: 8bit\\\\n\"');\n if (locale) {\n lines.push(`\"Language: ${locale}\\\\n\"`);\n }\n lines.push('\"MIME-Version: 1.0\\\\n\"');\n lines.push('');\n\n for (const [msgid, msgstr] of Object.entries(content)) {\n if (typeof msgstr !== 'string') continue;\n\n lines.push(`msgid \"${escapePO(msgid)}\"`);\n lines.push(`msgstr \"${escapePO(msgstr)}\"`);\n lines.push('');\n }\n\n return `${lines.join('\\n')}\\n`;\n};\n\n/**\n * PO payload codec bridging {@link parsePO} / {@link serializePO} to the\n * sync-plugin kit.\n */\nexport const poCodec: FormatCodec = {\n parse: parsePO,\n serialize: (content, { locale }) => serializePO(content, locale),\n};\n"],"mappings":";AAEA,MAAM,cAAc,QAClB,IACG,QAAQ,QAAQ,IAAI,CAAC,CACrB,QAAQ,QAAQ,GAAI,CAAC,CACrB,QAAQ,QAAQ,IAAI,CAAC,CACrB,QAAQ,QAAQ,IAAG,CAAC,CACpB,QAAQ,SAAS,IAAI;AAE1B,MAAM,YAAY,QAChB,IACG,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,MAAM,MAAK,CAAC,CACpB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,OAAO,KAAK;;;;;AAMzB,MAAa,WAAW,gBAAgD;CACtE,MAAM,SAAiC,CAAC;CACxC,MAAM,QAAQ,YACX,QAAQ,SAAS,IAAI,CAAC,CACtB,QAAQ,OAAO,IAAI,CAAC,CACpB,MAAM,IAAI;CAEb,IAAI,QAAQ;CACZ,IAAI,SAAS;CACb,IAAI,eAA0C;CAE9C,MAAM,iBAAiB;EACrB,IAAI,UAAU,IACZ,OAAO,SAAS;EAElB,QAAQ;EACR,SAAS;EACT,eAAe;CACjB;CAEA,KAAK,MAAM,QAAQ,OAAO;EAExB,IAAI,KAAK,WAAW,GAAG,GAAG;EAE1B,IAAI,KAAK,KAAK,MAAM,IAAI;GACtB,SAAS;GACT;EACF;EAEA,MAAM,aAAa,KAAK,MAAM,+BAA+B;EAC7D,IAAI,aAAa,IAAI;GAEnB,SAAS;GACT,QAAQ,WAAW,WAAW,EAAE;GAChC,eAAe;GACf;EACF;EAEA,MAAM,cAAc,KAAK,MAAM,gCAAgC;EAC/D,IAAI,cAAc,IAAI;GACpB,SAAS,WAAW,YAAY,EAAE;GAClC,eAAe;GACf;EACF;EAGA,MAAM,YAAY,KAAK,MAAM,uBAAuB;EACpD,IAAI,YAAY,IAAI;GAClB,IAAI,iBAAiB,SACnB,SAAS,WAAW,UAAU,EAAE;QAC3B,IAAI,iBAAiB,UAC1B,UAAU,WAAW,UAAU,EAAE;GAEnC;EACF;EAGA,eAAe;CACjB;CAGA,SAAS;CAET,OAAO;AACT;;;;;AAMA,MAAa,eACX,SACA,WACW;CACX,MAAM,QAAkB,CAAC;CAGzB,MAAM,KAAK,YAAU;CACrB,MAAM,KAAK,aAAW;CACtB,MAAM,KAAK,gDAA8C;CACzD,MAAM,KAAK,wCAAsC;CACjD,IAAI,QACF,MAAM,KAAK,cAAc,OAAO,KAAK;CAEvC,MAAM,KAAK,0BAAwB;CACnC,MAAM,KAAK,EAAE;CAEb,KAAK,MAAM,CAAC,OAAO,WAAW,OAAO,QAAQ,OAAO,GAAG;EACrD,IAAI,OAAO,WAAW,UAAU;EAEhC,MAAM,KAAK,UAAU,SAAS,KAAK,EAAE,EAAE;EACvC,MAAM,KAAK,WAAW,SAAS,MAAM,EAAE,EAAE;EACzC,MAAM,KAAK,EAAE;CACf;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;;;;;AAMA,MAAa,UAAuB;CAClC,OAAO;CACP,YAAY,SAAS,EAAE,aAAa,YAAY,SAAS,MAAM;AACjE"}
|
package/dist/esm/syncPO.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPO.mjs","names":[],"sources":["../../src/syncPO.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { DictionaryLocation } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\n// Re-exported for backward compatibility: these helpers used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\nexport { parsePO, serializePO } from './poFormat';\n\nexport type SyncPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncPO({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.po`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncPO({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Two-way PO synchronization plugin: ingests gettext PO files as dictionaries\n * and writes the merged build output back to the same files.\n */\nexport const syncPO = async (options: SyncPOPluginOptions): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-po::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; there is no namespace level\n // to split on, regardless of the source pattern shape.\n splitKeys: false,\n });\n};\n"],"mappings":";;;;;;;;;AA8DA,MAAa,SAAS,OAAO,YAAkD;CAM7E,MAAM,kBAAkB,YAAY,MAJR,qBAC1B,QAAQ,QACR,4BAA4B,WAAW,
|
|
1
|
+
{"version":3,"file":"syncPO.mjs","names":[],"sources":["../../src/syncPO.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { DictionaryLocation } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { poCodec } from './poFormat';\n\n// Re-exported for backward compatibility: these helpers used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\nexport { parsePO, serializePO } from './poFormat';\n\nexport type SyncPOPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncPO({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.po`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transforms PO files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncPO({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.po`,\n * location: 'plugin-i18next-po',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is 0.\n */\n priority?: number;\n};\n\n/**\n * Two-way PO synchronization plugin: ingests gettext PO files as dictionaries\n * and writes the merged build output back to the same files.\n */\nexport const syncPO = async (options: SyncPOPluginOptions): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-po::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-po',\n adapter: createFileAdapter({\n source: options.source,\n codec: poCodec,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: 'po',\n // PO files are flat msgid → msgstr records; there is no namespace level\n // to split on, regardless of the source pattern shape.\n splitKeys: false,\n });\n};\n"],"mappings":";;;;;;;;;AA8DA,MAAa,SAAS,OAAO,YAAkD;CAM7E,MAAM,kBAAkB,YAAY,MAJR,qBAC1B,QAAQ,QACR,4BAA4B,WAAW,YAAY,CACrD;CAGA,OAAO,iBAAiB;EACtB,MAAM;EACN,SAAS,kBAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAO;GACP,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ;EAGR,WAAW;CACb,CAAC;AACH"}
|
package/dist/types/loadPO.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadPO.d.ts","names":[],"sources":["../../src/loadPO.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadPO.d.ts","names":[],"sources":["../../src/loadPO.ts"],"mappings":";;;;KASY;;;;;;;;;;;;EAYV,QAAQ;;;;;;;;;;;;;;EAeR,SAAS;;;;;;;;;;;;;;;;;;;EAoBT;;;;;;;;EASA;;;;;;cAOW,SAAM,SAAa,wBAAsB"}
|
package/dist/types/poFormat.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poFormat.d.ts","names":[],"sources":["../../src/poFormat.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"poFormat.d.ts","names":[],"sources":["../../src/poFormat.ts"],"mappings":";;;;;;cAsBa,UAAO,wBAA0B;;;;;cAsEjC,cAAW,SACb,yBAAuB;;;;;cA+BrB,SAAS"}
|
package/dist/types/syncPO.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { FilePathPattern } from "@intlayer/types/filePathPattern";
|
|
|
3
3
|
import { Plugin } from "@intlayer/types/plugin";
|
|
4
4
|
import { extractKeyAndLocaleFromPath } from "@intlayer/engine/syncPluginKit";
|
|
5
5
|
import { DictionaryLocation } from "@intlayer/types/dictionary";
|
|
6
|
-
|
|
7
6
|
//#region src/syncPO.d.ts
|
|
8
7
|
type SyncPOPluginOptions = {
|
|
9
8
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncPO.d.ts","names":[],"sources":["../../src/syncPO.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"syncPO.d.ts","names":[],"sources":["../../src/syncPO.ts"],"mappings":";;;;;;KAeY;;;;;;;;;;;EAWV,QAAQ;;;;;;;;;;;;;;;;;;;EAoBR,WAAW;;;;;;;;EASX;;;;;;cAOW,SAAM,SAAmB,wBAAsB,QAAQ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/sync-po-plugin",
|
|
3
|
-
"version": "9.0.0-canary.
|
|
3
|
+
"version": "9.0.0-canary.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A plugin for Intlayer that syncs Portable Object (.po) files to dictionaries.",
|
|
6
6
|
"keywords": [
|
|
@@ -72,20 +72,20 @@
|
|
|
72
72
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@intlayer/config": "9.0.0-canary.
|
|
76
|
-
"@intlayer/core": "9.0.0-canary.
|
|
77
|
-
"@intlayer/engine": "9.0.0-canary.
|
|
78
|
-
"@intlayer/types": "9.0.0-canary.
|
|
75
|
+
"@intlayer/config": "9.0.0-canary.19",
|
|
76
|
+
"@intlayer/core": "9.0.0-canary.19",
|
|
77
|
+
"@intlayer/engine": "9.0.0-canary.19",
|
|
78
|
+
"@intlayer/types": "9.0.0-canary.19",
|
|
79
79
|
"fast-glob": "3.3.3"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@types/node": "
|
|
82
|
+
"@types/node": "26.1.1",
|
|
83
83
|
"@utils/ts-config": "1.0.4",
|
|
84
84
|
"@utils/ts-config-types": "1.0.4",
|
|
85
85
|
"@utils/tsdown-config": "1.0.4",
|
|
86
86
|
"rimraf": "6.1.3",
|
|
87
|
-
"tsdown": "0.
|
|
88
|
-
"typescript": "
|
|
87
|
+
"tsdown": "0.22.12",
|
|
88
|
+
"typescript": "7.0.2",
|
|
89
89
|
"vitest": "4.1.10"
|
|
90
90
|
},
|
|
91
91
|
"engines": {
|