Using aurelia-i18n with webpack + typescript + aurelia's own loader
alankila opened this issue · 5 comments
I'm submitting a bug report
Note: this is really a request for clarification of documentation.
- Library Version:
2.1.2, project skeleton as created by aurelia-cli 0.33.0
Please tell us about your environment:
-
Operating System:
OSX 10.13.4 -
Node Version:
10.0.0 -
NPM Version:
6.0.0 -
JSPM OR Webpack AND Version
webpack 2.1.2 -
Browser:
all -
Language:
TypeScript 2.8.3
Current behavior:
I was having a hard time figuring out how to bundle localization files with webpack using aurelia's own loader. The instructions on Aurelia I18N page do not really cover how tell webpack to bundle my translation files into the application bundle. If they are not bundled, then i18next of course fails resolving them at runtime.
Basically, no matter what I did, I could not require/import the .json files from either TS or template files, and I had no idea what to write to webpack config to make it bundle these files either. I was, however, able to determine that aurelia-i18n itself was working fine. Therefore, I designed a workaround.
Firstly, I converted the localization files from .json to .ts files, so that I could import them as regular modules. Basically, I just prepended "export default" in front of the JSON and changed the file suffix.
Then, I wrote a custom backend for i18next that does exactly this:
import fi from './fi';
import sv from './sv';
import en from './en';
export class LocaleBackend {
type = "backend";
init() {
}
read(language: string, namespace: string, callback: (error: string | undefined, data: {}) => void) {
if (language == "fi") {
callback(undefined, fi);
return;
}
if (language == "sv") {
callback(undefined, sv);
return;
}
callback(undefined, en);
}
}
This class was used as backend for i18next in place of the Backend.with(aurelia.loader) that I had before:
instance.i18next.use(new LocaleBackend());
-
Expected/desired behavior:
I would appreciate some clarification in the documentation on how to make webpack bundle the .json files under locales/ so that they would become available using aurelia's standard loader. I think there needs to be some kind of static command in webpack.config to do so, because there are no direct references to the .json files that webpack could statically see. -
What is the motivation / use case for changing the behavior?
Extending aurelia with non-standard modules has become much easier with webpack, especially as you can just use modules now, and they get bundled automatically. Unfortunately, the fact that there was no documented way (that I could see) for adding the localization files in the bundle was an oversight that turned a 5-minute job into a much longer and more painful one.
Thanks for looking into this. Sadly I cant really help with this one as Im trying to avoid using webpack wherever I can so my knowledge is too limited. Raising this issue over at Gitter or our Discourse forum should help bringing people with a better expertise.
@alankila @zewa666
previous didn't work for me in the end.
but i did get https://github.com/atroo/i18next-resource-store-loader to work and have the translation.jsons bundled in the app bundle. no webpack.config edits needed (as a json loader is usually included already)
sample file structure:
main.js
config\locale\en\tanslation.json
config\locale\de\tanslation.json
config\locale\index.js //<-- just an empty file as root pointer for the resource store loader
in main.js
import resBundle from "i18next-resource-store-loader!./config/locale/index.js" //<--root pointer relative to main
export function configure(aurelia) {
aurelia.use
//...
/* @see https://github.com/aurelia/i18n */
.plugin(PLATFORM.moduleName('aurelia-i18n'), instance => {
// adapt options to your needs (see http://i18next.com/pages/doc_init.html)
let language = localStorage.getItem('language');
return instance.setup({
resources: resBundle,
lng : language || appConfig.defaultLocale.language,
attributes : ['t'],
fallbackLng: language || appConfig.defaultLocale.language,
debug : false,
});
})
edit: type: ‘javascript/auto
also works. see https://discourse.aurelia.io/t/solved-aurelia-i18n-webpack-4-help-needed/
I ended up referencing a javascript file. Is there anything wrong with that?
It seems more explicit and easier to reason about.
Configuration:
import translarionResource from "./locales/translation"
...
aurelia.use.plugin(PLATFORM.moduleName('aurelia-i18n'), (instance: I18N) => {
let aliases = ['t', 'i18n'];
TCustomAttribute.configureAliases(aliases);
return instance.setup({
debug: false,
resources: translarionResource,
lng: 'en',
fallbackLng: 'en',
defaultNS: 'global',
attributes: aliases,
});
});
./locales/translation.js:
export default {
en: {
global: {
"userName": "User Name",
...
}
}
totally fine. the only downside could be if you load multiple translations that all are eagerly loaded and increase bandwidth