UNPKG

next-intl

Version:

Internationalization (i18n) for Next.js

94 lines (89 loc) 2.97 kB
import POParser from 'po-parser'; import { setNestedProperty, getSortedMessages } from '../../utils.js'; import { defineCodec } from '../ExtractorCodec.js'; var POCodec = defineCodec(() => { // See also https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html const DEFAULT_METADATA = { // Recommended by spec 'Content-Type': 'text/plain; charset=utf-8', 'Content-Transfer-Encoding': '8bit', // Otherwise other tools might set this 'X-Generator': 'next-intl', // Crowdin defaults to using msgid as source key 'X-Crowdin-SourceKey': 'msgstr' }; // Move all parts before the last dot to msgctxt const NAMESPACE_SEPARATOR = '.'; // Metadata is stored so it can be retained when writing const metadataByLocale = new Map(); return { decode(content, context) { const catalog = POParser.parse(content); if (catalog.meta) { metadataByLocale.set(context.locale, catalog.meta); } const messages = catalog.messages || []; return messages.map(msg => { const { extractedComments, msgctxt, msgid, msgstr, ...rest } = msg; if (extractedComments && extractedComments.length > 1) { throw new Error(`Multiple extracted comments are not supported. Found ${extractedComments.length} comments for msgid "${msgid}".`); } return { ...rest, id: msgctxt ? [msgctxt, msgid].join(NAMESPACE_SEPARATOR) : msgid, message: msgstr, ...(extractedComments && extractedComments.length > 0 && { description: extractedComments[0] }) }; }); }, encode(messages, context) { const encodedMessages = getSortedMessages(messages).map(msg => { const { description, id, message, ...rest } = msg; const lastDotIndex = id.lastIndexOf(NAMESPACE_SEPARATOR); const hasNamespace = id.includes(NAMESPACE_SEPARATOR); const msgid = hasNamespace ? id.slice(lastDotIndex + NAMESPACE_SEPARATOR.length) : id; return { msgid, msgstr: message, ...(description && { extractedComments: [description] }), ...(hasNamespace && { msgctxt: id.slice(0, lastDotIndex) }), ...rest }; }); return POParser.serialize({ meta: { Language: context.locale, ...DEFAULT_METADATA, ...metadataByLocale.get(context.locale) }, messages: encodedMessages }); }, toJSONString(source, context) { const parsed = this.decode(source, context); const messagesObject = {}; for (const message of parsed) { setNestedProperty(messagesObject, message.id, message.message); } return JSON.stringify(messagesObject); } }; }); export { POCodec as default };