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

ES Modules #511

Closed RobbeCl closed 1 year ago

RobbeCl commented 1 year ago

It is not possible to use this package in an ES module because of the use of __dirname in the code: https://github.com/mashpie/i18n-node/blob/v0.15.0/i18n.js#L125. What it be possible to use another approach?

Or export a file that can be used by a ES module project

mashpie commented 1 year ago

__dirname is CJS only while import.meta.url is ESM only. So i18n would need some transpiler to support both package types... eventually there'll be major release for ESM only dropping CJS support as proposed by https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

For now you might try with explicitly setting directory instead of falling back to defaults, ie.:

import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { I18n } from 'i18n';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const i18n = new I18n({
  locales: ['en', 'de'],
  directory: path.join(__dirname, 'locales')
});

now you get back full control about your locales directory setting

RobbeCl commented 1 year ago

Thanks for the response. I'll wait for the transition to ESM

mashpie commented 1 year ago

actually node (at least v18+) works as expected and resolves directory to ./locales relative to i18n.js - no matter if I try with .cjs or .mjs or set "type": "module" in package.json.

Leaving directory to default has never been a good choice as it will always use that node_modules/i18n/locales path which won't be part of any modern deployment strategy.

Sites/tmp/i18n-esm is πŸ“¦ v0.0.0 via  v18.12.1
❯ tree node_modules/i18n/ -L 2
node_modules/i18n/
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
β”œβ”€β”€ SECURITY.md
β”œβ”€β”€ i18n.js
β”œβ”€β”€ index.js
β”œβ”€β”€ locales
β”‚Β Β  β”œβ”€β”€ de.json
β”‚Β Β  └── en.json
β”œβ”€β”€ node_modules
β”‚Β Β  └── mustache
└── package.json

3 directories, 8 files

So, you should always set directory anyways

RobbeCl commented 1 year ago

Well, the problem I get that I get errors when importing i18n because of this line: 'https://github.com/mashpie/i18n-node/blob/v0.15.0/i18n.js#L125'

mashpie commented 1 year ago

do you have a reproduction repo? I just tried both https://github.com/mashpie/i18n-esm-cjs-example and don't get any errors

tashigeekyants commented 1 year ago

same issue


  /**  Localization   */
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
  /** Configure localization */
  i18n.configure({
    locales: ['en_us', 'de_de'],
    defaultLocale: 'en_us',
    directory: path.join(__dirname, 'locales'),
  });
  app.use(i18n.init);
  app.use(setLocale);

  // routes
  app.get('/', async function (req: Request, res: Response) {
    res.json({ message: i18n.__('server-running') });
  });

above code works in dev, not in prod. jsons file are empty

mashpie commented 1 year ago

works in dev, not in prod. jsons file are empty

so, where do dev and prod differ?

tashigeekyants commented 1 year ago

works in dev, not in prod. jsons file are empty

so, where do dev and prod differ?

when I run dev tsc && ts-node index.ts, It is taking the proper locale path (src/locales).
But when I run npm run build locales folder is not copy in the dist folder hence run dist/index.js also didn't work. So I end up using copyfiles package to copy locales folder in dist folder while building

mashpie commented 1 year ago

Well, any kind of build step will most probably run within a different env than the resulting script. Same applies to dynamic values of __dirname or import.meta. So you canβ€˜t really rely on them. Instead, you should treat the directory setting like any other config and set that explicitly.