UNPKG

biblatex-csl-converter

Version:

Bibliography format converter: BibLaTeX, BibTeX, CSL-JSON, RIS, ENW, EndNote XML, Citavi, DOCX citations, ODT citations — parse, convert, and export with round-trip fidelity

237 lines (222 loc) 6.24 kB
/** * i18n module for biblatex-csl-converter * * Provides human-readable labels for reference types, field names, field help * text, and option values in multiple languages. * * ## Structure of a locale object * ```json * { * "fieldTitles": { "<fieldKey>": "<label>", … }, * "fieldHelp": { "<fieldKey>": "<help text>", … }, * "typeTitles": { "<typeKey>": "<label>", … }, * "fieldTitlesByType": { "<typeKey>": { "<fieldKey>": "<label>" }, … }, * "langidOptions": { "<langidKey>": "<label>", … }, * "otherOptions": { "<optionKey>": "<label>", … } * } * ``` * * ## Per-type field overrides (`fieldTitlesByType`) * Some field names carry a different human meaning depending on the reference * type. For example, the `author` field of a `video` entry is conventionally * labelled "Director(s)" rather than "Author(s)". Use `getFieldTitle()` which * checks `fieldTitlesByType[type][field]` first and falls back to * `fieldTitles[field]`. * * ## Option split * `langidOptions` covers every value valid for the BibLaTeX `langid` field * (including BibTeX-level aliases such as `pinyin`, `american`, `english`). * `otherOptions` covers editortype values, pagination values, pubstate values, * and `type` sub-field values (mathesis, phdthesis, techreport, …). * * ## Locale data * The locale data lives in `src/i18n/locales.ts`, which is auto-generated by: * npm run compile_i18n * * ## Supported languages * ar, bg, cs, de, en, es, fr, it, ja, ko, nl, pl, pt-BR, pt-PT, ru, sv, tr, zh */ // --------------------------------------------------------------------------- // Types (re-exported from ./types.ts to keep the public API stable) // --------------------------------------------------------------------------- export type { FieldHelp, FieldTitles, FieldTitlesByType, LangidOptions, Locale, OtherOptions, TypeTitles, } from "./types" import type { Locale } from "./types" // --------------------------------------------------------------------------- // Locale registry // --------------------------------------------------------------------------- import { ar, bg, cs, da, de, en, es, fr, it, ja, ko, nb, nl, pl, ptBR, ptPT, ru, sv, tr, zh, } from "./locales" export { ar, bg, cs, da, de, en, es, fr, it, ja, ko, nb, nl, pl, ptBR, ptPT, ru, sv, tr, zh, } /** * All built-in locales keyed by IETF language tag. * * Consumers that need a language not listed here can supply their own `Locale` * object — every public helper accepts a `Locale` directly. */ export const locales: Readonly<Record<string, Locale>> = Object.freeze({ ar, bg, cs, da, de, en, es, fr, it, ja, ko, nl, nb, pl, "pt-BR": ptBR, "pt-PT": ptPT, ru, sv, tr, zh, }) // --------------------------------------------------------------------------- // Helper functions // --------------------------------------------------------------------------- /** * Return the `Locale` for *lang*, falling back to English when not available. * * Lookup order: * 1. Exact tag (e.g. `"pt-BR"`) * 2. Base subtag (e.g. `"pt"` from `"pt-BR"`) * 3. English fallback * * @example * getLocale("de") // → locales.de * getLocale("pt-BR") // → locales["pt-BR"] * getLocale("zh") // → locales.en (fallback) */ export function getLocale(lang: string): Locale { if (lang in locales) { return locales[lang] } const base = lang.split("-")[0] if (base !== lang && base in locales) { return locales[base] } return locales.en } /** * Return the human-readable label for *fieldKey* in the context of *typeKey*, * using *locale* for the translation. * * Checks `locale.fieldTitlesByType[typeKey][fieldKey]` first, then falls back * to `locale.fieldTitles[fieldKey]`, and finally to the raw key itself. * * @example * getFieldTitle(locales.en, "book", "author") // → "Author(s)" * getFieldTitle(locales.en, "video", "author") // → "Director(s)" * getFieldTitle(locales.de, "book", "author") // → "Autor(en)" */ export function getFieldTitle( locale: Locale, typeKey: string, fieldKey: string, ): string { return ( locale.fieldTitlesByType[typeKey]?.[fieldKey] ?? locale.fieldTitles[fieldKey] ?? fieldKey ) } /** * Return the human-readable label for *typeKey* in *locale*, falling back to * the raw key if not found. * * @example * getTypeTitle(locales.fr, "article-journal") // → "Article de revue" */ export function getTypeTitle(locale: Locale, typeKey: string): string { return locale.typeTitles[typeKey] ?? typeKey } /** * Return the help/hint text for *fieldKey* in *locale*, or `undefined` when * no help text is defined for that field. * * @example * getFieldHelp(locales.en, "date") // → "In <em>Extended Date Time Format</em>…" * getFieldHelp(locales.en, "title") // → undefined */ export function getFieldHelp( locale: Locale, fieldKey: string, ): string | undefined { return locale.fieldHelp[fieldKey] } /** * Return the human-readable label for a `langid` field value in *locale*, * falling back to the raw key if not found. * * @example * getLangidTitle(locales.de, "french") // → "Französisch" * getLangidTitle(locales.en, "brportuguese") // → "Brazilian Portuguese" */ export function getLangidTitle(locale: Locale, langidKey: string): string { return locale.langidOptions[langidKey] ?? langidKey } /** * Return the human-readable label for a non-language option value in *locale* * (i.e. an `editortype`, `pagination`, `pubstate`, or `type` sub-field value), * falling back to the raw key if not found. * * @example * getOtherOptionTitle(locales.de, "phdthesis") // → "Ph.D. These" * getOtherOptionTitle(locales.en, "inpreparation") // → "In preparation" */ export function getOtherOptionTitle(locale: Locale, optionKey: string): string { return locale.otherOptions[optionKey] ?? optionKey }