Storage Interface
The storage interface provides a way to implement a custom storage handler for catalogs. The handler is provided to the adapter config as storage.
An item is a unit (can be a message or a URL) extracted from the source code or the URL patterns you configured, with full translation and reference details.
type FileRefEntry = { link?: string | undefined // for URLs placeholders: [number, string][]}
type FileRef = { file: string /** * multiple references in the same file * null when there is no link or placeholders just that it's referenced */ refs: (FileRefEntry | null)[]}
interface Item { context?: string | undefined translations: Map<string, string[]> references: FileRef[] urlAdapters: string[] // for URLs // for things that should survive the round trip with the storage [key: string]: unknown}And this is the unit that forms the basis for what exchanged with wuchale.
Plural rules
Section titled “Plural rules”An additional thing that has to be stored with the translations is the plural rules.
type PluralRule = { nplurals: number plural: string}
type PluralRules = Map<string, PluralRule>Exchanged data
Section titled “Exchanged data”There are just two exchange interactions with wuchale: saving data and loading data. And what the storage has to exchange is this:
type SaveData = { pluralRules: PluralRules // will always be provided items: Item[]}type LoadData = { pluralRules?: PluralRules | undefined // optional if it's the first time etc, will be filled by the default one items: Item[]}File system
Section titled “File system”Since almost all of the data exchanged is text files, wuchale provides a file
system abstraction layer that reads and handles non existing file errors,
returning null, and such conveniences. However, the reason for its existence
is swappability for testing and for the npx wuchale check --full command
which goes through the normal process of extraction but doesn't write anything
because it uses a read-only instance of the file system layer. To make a new
storage interface work like that, you can use this layer, provided by wuchale.
It looks like this:
type FS = { read(file: string): string | null | Promise<string | null> write(file: string, content: string): void | Promise<void> mkdir(path: string): void | Promise<void> exists(path: string): boolean | Promise<boolean> unlink(path: string): boolean | Promise<boolean>}Whole interface
Section titled “Whole interface”Putting it all together, what wuchale expects as a storage is a StorageFactory function that accepts StorageFactoryOpts options from wuchale, and returns a CatalogStorage object.
type StorageFactoryOpts = { locales: string[] root: string /** shared locale artifacts directory from the top-level config */ localesDir: string /** whether the url is configured, can use to load separate url files */ haveUrl: boolean sourceLocale: string fs: FS}
type CatalogStorage = { /** * the key to check if two storages share the same location * e.g. this can be the dir for the pofile storage * two storages with same keys means they are the same/shared */ key: string load(): LoadData | Promise<LoadData> save(data: SaveData): void | Promise<void> /** the files controlled by this storage, for e.g. for Vite to watch */ files: string[]}
type StorageFactory = (opts: StorageFactoryOpts) => CatalogStorage | Promise<CatalogStorage>