mashpie / i18n-node

Lightweight simple translation module for node.js / express.js with dynamic json storage. Uses common __('...') syntax in app and templates.
MIT License
3.09k stars 421 forks source link

How to set up i18n for node.js for multiple resource files of same language? #439

Closed TheInvoker closed 2 years ago

TheInvoker commented 4 years ago

I am trying to set up i18n for different json files of the the same language. The convention is every js file has a /locales/en.json in its folder. I have this so far

const i18n = require("i18n"); i18n.configure({ locales: ["en"], directory: __dirname + "/locales" });

This works for one file, but if I do this on another js file, this overrides the i18n with the json file of the most recent call, and the resource of the first one will be gone. I believe the trick is to load new instances of i18n, but this is a singelton with no api to make a new copy. I tried freshimport but it didn't work either.

Anyone know how to fix this?

mashpie commented 4 years ago

Currently i18n still is build and exported as a singleton. So you can't have different instances. But you might come around by implementing your own catalog loading -
checkout the staticCatalog config option: https://github.com/mashpie/i18n-node#some-words-on-staticcatalog-option

TheInvoker commented 4 years ago

I fixed this by clearing all entries from require.cache that has i18n in its file path.

mashpie commented 4 years ago

alright - another option would be to use https://www.npmjs.com/package/import-fresh like in https://github.com/mashpie/i18n-node/blob/master/test/i18n.configureMustache.js

Spown commented 4 years ago

Actually I've tackled the same problem in my fork. And in order to preserve backward compat. I've introduced a .Constructor method. So I can spawn additional i18n instances, configured to use different files.

the commit also introduces __e ("key_exists") checker method. Thus allowing a sort of inheretance/overwrite chain of i18n instances: if the current one doesn't have a registered translation - you can ask the next one. The current version won't tell you that, because calling for a key, would either create it or simply return the key back, iirc.

TheInvoker commented 4 years ago

Ive tried the import fresh, it didn't seem to work.

Spown commented 4 years ago

@TheInvoker you can try my fork

 "dependencies": {
    "i18n": "github:Spown/i18n-node",

then you can spawn new instances and configure each one with different paths

//file 1
var i18n = require("i18n")
;
i18n.configure({
    directory: __dirname + "/locales"
})
//file 2
// or "new require("i18n").Constructor()" but it's a more messy one.
// better use the initial singleton across all files, by either making it global or passing through in some way
var otherI18n =  new i18n.Constructor()
;
otherI18n.configure({
    directory: __dirname + "/locales"
})
mashpie commented 4 years ago

would you mind trying the fresh released constructor support of v0.12.0 :)

see https://github.com/mashpie/i18n-node/tree/master#as-instance

TheInvoker commented 4 years ago

I am using typescript, and it doesn't seem to support this. I am getting

Module '"i18n"' has no exported member 'I18n'.

Spown commented 4 years ago

@mashpie also, can you please make .Constructor an alias to .I18n?

mashpie commented 4 years ago

@TheInvoker double of #324

@Spown well it's name is I18n - I could add dozens of aliases to fulfil all types of requests. How about wrapping your own alias/adapter, like so:

// ./i18n-alias.js
const i18n = require('i18n');
module.exports.Constructor = i18n;

and use it like so:

var i18n = require('./i18n-alias')

var otherI18n =  new i18n.Constructor()

/**
 * { Constructor: [Function: I18n] }
 */
console.log(i18n);

/**
 * {
 *   version: '0.12.0',
 *   configure: [Function: i18nConfigure],
 *   init: [Function: i18nInit],
 *   __: [Function: i18nTranslate],
 *   __mf: [Function: i18nMessageformat],
 *   __l: [Function: i18nTranslationList],
 *   __h: [Function: i18nTranslationHash],
 *   __n: [Function: i18nTranslatePlural],
 *   setLocale: [Function: i18nSetLocale],
 *   getLocale: [Function: i18nGetLocale],
 *   getCatalog: [Function: i18nGetCatalog],
 *   getLocales: [Function: i18nGetLocales],
 *   addLocale: [Function: i18nAddLocale],
 *   removeLocale: [Function: i18nRemoveLocale]
 * }
 */
console.log(otherI18n);