Skip to content

Commit 9f368fe

Browse files
authored
Merge pull request #90 from fabscale/fn/locales-import
Update locale import to be more Embroider compatible
2 parents 6b3fd24 + e69a458 commit 9f368fe

File tree

28 files changed

+1310
-619
lines changed

28 files changed

+1310
-619
lines changed

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ ember gettext:convert --locale=de
106106

107107
This project is basically a fork of [ember-l10n](https://github.com/Cropster/ember-l10n). It is _mostly_ compatible with it, and can be migrated with some minor steps:
108108

109-
0. Run `yarn remove ember-l10n && yarn add @ember-gettext/ember-l10n @ember-gettext/gettext-parser --dev --tilde`
109+
0. Run `yarn remove ember-l10n && yarn add @ember-gettext/ember-l10n @ember-gettext/gettext-parser --dev --tilde && ember generate ember-l10n`
110110
1. Replace the `ember-l10n` key in your `config/environment.js` with `@ember-gettext/ember-l10n`
111111
2. Replace usage of `<GetText>` with `<L10nMessage>`
112112
3. Replace usage of `{{pt}}` with `{{t}}` with an additional argument, as well as `{{pn}}` with `{{n}}`
113-
4. Move your locale .json files from `public/assets/locales` to `translations`
114-
5. Use the new streamlined `ember gettext:extract` and `ember gettext:convert` commands instead of `ember l10n:XXX`
113+
4. Move your .po & .pot files to `./translations` folder
114+
5. Remove locale .json files from `public/assets/locales`
115+
6. Use the new streamlined `ember gettext:extract` and `ember gettext:convert` commands instead of `ember l10n:XXX`
116+
7. Run `ember gettext:convert` to convert all .po files to locale .json files to get started

packages/ember-l10n/README.md

+18-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ In the ember-l10n workflow, you use the `t`, and `n` helpers and `l10n.t()` / `l
88

99
## Compatibility
1010

11+
- **Embroider only!!**
1112
- Ember.js v3.25 or above
1213
- Ember CLI v3.20 or above
1314
- Node.js v12 or above
1415

16+
This addon is optimized for Embroider. It is probably possible to also use it without Embroider, but you'll need to adjust the generated import map yourself.
17+
1518
## Installation
1619

1720
```
@@ -33,9 +36,18 @@ let ENV = {
3336
};
3437
```
3538

39+
In order to ensure the locales are lazy loaded, you'll need to add this to your `ember-cli-build.js` file:
40+
41+
```js
42+
return require('@embroider/compat').compatBuild(app, Webpack, {
43+
// Ensure `locales` are considered static & lazy loaded
44+
staticAppPaths: ['locales'],
45+
});
46+
```
47+
3648
## Usage
3749

38-
Translations are provided as `.json` files under `/translations`, e.g. `/translations/de.json`.
50+
Translations are provided as `.json` files under `/app/locales`, e.g. `/app/locales/de.json`.
3951
They can be generated with the separate parser addon.
4052

4153
To use translations in your app, you can use either the provided helpers, a contextual component or a service:
@@ -180,11 +192,7 @@ will be available as `{{text}}` to the named block.
180192

181193
Locale files can be generated with [gettext-parser](./../gettext-parser).
182194

183-
ember-l10n expects properly formatted .json files (e.g. `de.json`, `en.json`) in the `./translations` folder of your app.
184-
These files will be automatically be moved to `assets/locales` at build time, e.g. `assets/locales/en.json`.
185-
186-
You will have to make sure to either let them be fingerprinted (which happens automatically by broccoli-asset-rev)
187-
or otherwise handle cache invalidation of these files yourself.
195+
ember-l10n expects properly formatted .json files (e.g. `de.json`, `en.json`) , by default in the `./app.locales` folder of your app.
188196

189197
### Locale detection
190198

@@ -204,6 +212,10 @@ export default class ApplicationRoute extends Route {
204212

205213
This will pick the first matching locale from the available locales for you.
206214

215+
## Updating from older versions
216+
217+
When updating from versions before 1.x, please run `ember generate ember-l10n` once to generate the required boilerplate files for you.
218+
207219
## Contributing
208220

209221
See the [Contributing](CONTRIBUTING.md) guide for details.

packages/ember-l10n/addon/services/l10n.js

+14-32
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@ import {
99
getMessages,
1010
getPluralMessage,
1111
} from '@ember-gettext/ember-l10n/utils/message-utils';
12-
import fetch from 'fetch';
1312
import { detectLocale } from '@ember-gettext/ember-l10n/utils/detect-locale';
1413
import { PluralFactory } from '@ember-gettext/ember-l10n/utils/plural-factory';
1514
import { buildWaiter } from '@ember/test-waiters';
1615

1716
const waiter = buildWaiter('ember-l10n:l10n');
1817

19-
// We cache locales - this is useful to avoid re-fetching the locale files e.g. in acceptance tests
20-
const LOCALE_CACHE = {};
21-
2218
export default class L10nService extends Service {
2319
@tracked locale;
2420
@tracked l10nTranslations;
@@ -29,12 +25,18 @@ export default class L10nService extends Service {
2925
availableLocales = ['en'];
3026
defaultPluralFactory;
3127

32-
// This will be replaced at build time via a babel plugin with the actual asset map
33-
_staticAssetMap;
28+
localeLoadingMap;
3429

3530
constructor() {
3631
super(...arguments);
3732

33+
this.localeLoadingMap = getOwner(this).lookup('ember-l10n:locales');
34+
assert(
35+
`It seems the locale map could not be loaded.
36+
Please run \`ember generate ember-l10n\` once to create the required boilerplate.`,
37+
this.localeLoadingMap
38+
);
39+
3840
let config = getOwner(this).resolveRegistration('config:environment');
3941
let l10nConfig = config['@ember-gettext/ember-l10n'];
4042
this._loadConfig(l10nConfig);
@@ -122,7 +124,7 @@ export default class L10nService extends Service {
122124
this.availableLocales.includes(locale)
123125
);
124126

125-
await this._loadLocaleFile(locale);
127+
await this._loadLocale(locale);
126128

127129
this.locale = locale;
128130

@@ -159,26 +161,20 @@ export default class L10nService extends Service {
159161
}
160162
}
161163

162-
async _loadLocaleFile(locale) {
163-
if (LOCALE_CACHE[locale]) {
164-
this.pluralFactory = new PluralFactory(locale);
165-
this.l10nTranslations = LOCALE_CACHE[locale];
166-
return;
167-
}
168-
164+
async _loadLocale(locale) {
169165
let localeData;
170166

171-
let localePath = this._staticAssetMap[locale];
167+
let loadFn = this.localeLoadingMap[locale];
172168

173169
assert(
174-
`ember-l10n: Cannot find locale file path for locale "${locale}"`,
175-
Boolean(localePath)
170+
`ember-l10n: Cannot find locale file for locale "${locale}"`,
171+
Boolean(loadFn)
176172
);
177173

178174
let token = waiter.beginAsync();
179175

180176
try {
181-
localeData = await this._fetch(localePath);
177+
localeData = await loadFn();
182178
} catch (error) {
183179
// eslint-disable-next-line no-console
184180
console.error(`ember-l10n: Error trying to fetch locale ${locale}`);
@@ -193,27 +189,13 @@ export default class L10nService extends Service {
193189
this.l10nTranslations = l10nTranslations;
194190
this.pluralFactory = new PluralFactory(locale);
195191

196-
LOCALE_CACHE[locale] = l10nTranslations;
197-
198192
waiter.endAsync(token);
199193
}
200194

201-
async _fetch(localePath) {
202-
let response = await fetch(localePath);
203-
return response.json();
204-
}
205-
206195
_validateLocales() {
207196
assert(
208197
`ember-l10n: Do not use the locale zh, as it is not a valid locale. Instead, use dedicated locales for traditional & simplified Chinese.`,
209198
!this.availableLocales.some((locale) => locale === 'zh')
210199
);
211200
}
212201
}
213-
214-
// This is mostly relevant for tests - normally you shouldn't have to ever use this
215-
export function clearLocaleCache() {
216-
for (let k in LOCALE_CACHE) {
217-
delete LOCALE_CACHE[k];
218-
}
219-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import localeMap from '<%= dasherizedPackageName %>/locales/index';
2+
3+
export function initialize(appInstance) {
4+
appInstance.register('ember-l10n:locales', localeMap, { instantiate: false });
5+
}
6+
7+
export default {
8+
initialize,
9+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const localeMap = {};
2+
3+
export default localeMap;
-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const getChannelURL = require('ember-source-channel-url');
4-
const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');
54

65
module.exports = async function () {
76
return {
@@ -39,36 +38,6 @@ module.exports = async function () {
3938
},
4039
},
4140
},
42-
{
43-
name: 'ember-default-with-jquery',
44-
env: {
45-
EMBER_OPTIONAL_FEATURES: JSON.stringify({
46-
'jquery-integration': true,
47-
}),
48-
},
49-
npm: {
50-
devDependencies: {
51-
'@ember/jquery': '^1.1.0',
52-
},
53-
},
54-
},
55-
{
56-
name: 'ember-classic',
57-
env: {
58-
EMBER_OPTIONAL_FEATURES: JSON.stringify({
59-
'application-template-wrapper': true,
60-
'default-async-observers': false,
61-
'template-only-glimmer-components': false,
62-
}),
63-
},
64-
npm: {
65-
ember: {
66-
edition: 'classic',
67-
},
68-
},
69-
},
70-
embroiderSafe(),
71-
embroiderOptimized(),
7241
],
7342
};
7443
};

packages/ember-l10n/ember-cli-build.js

+4-15
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33
const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
44

55
module.exports = function (defaults) {
6-
let app = new EmberAddon(defaults, {
7-
'ember-fetch': {
8-
preferNative: true,
9-
},
10-
fingerprint: {
11-
extensions: ['js', 'css', 'png', 'jpg', 'gif', 'map', 'json'],
12-
},
13-
});
6+
let app = new EmberAddon(defaults, {});
147

158
/*
169
This build file specifies the options for the dummy test app of this
@@ -19,12 +12,8 @@ module.exports = function (defaults) {
1912
behave. You most likely want to be modifying `./index.js` or app's build file
2013
*/
2114

22-
const { maybeEmbroider } = require('@embroider/test-setup');
23-
return maybeEmbroider(app, {
24-
skipBabel: [
25-
{
26-
package: 'qunit',
27-
},
28-
],
15+
const { Webpack } = require('@embroider/webpack');
16+
return require('@embroider/compat').compatBuild(app, Webpack, {
17+
staticAppPaths: ['locales'],
2918
});
3019
};

packages/ember-l10n/index.js

-81
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,5 @@
11
'use strict';
2-
const funnel = require('broccoli-funnel');
3-
const CreateLocaleAssetMap = require('./lib/create-locale-asset-map');
4-
5-
const DEST_DIR = 'assets/locales';
62

73
module.exports = {
84
name: require('./package').name,
9-
10-
included() {
11-
this._super.included.apply(this, arguments);
12-
13-
this._fixFingerprintingSettings();
14-
},
15-
16-
treeForPublic() {
17-
let localeTree = funnel(this._getTranslationsFolder(), {
18-
destDir: DEST_DIR,
19-
include: ['*.json'],
20-
});
21-
22-
return localeTree;
23-
},
24-
25-
setupPreprocessorRegistry(type, registry) {
26-
if (type !== 'self') {
27-
return;
28-
}
29-
30-
let translationsFolder = this._getTranslationsFolder();
31-
registry.add('js', new CreateLocaleAssetMap({ translationsFolder }));
32-
},
33-
34-
_fixFingerprintingSettings() {
35-
let app = this._findHost();
36-
37-
// Fix fingerprinting options to work
38-
if (
39-
app.options?.fingerprint?.enabled !== false &&
40-
app.project.findAddonByName('broccoli-asset-rev')
41-
) {
42-
let fingerprintOptions = app.options.fingerprint;
43-
44-
let infoMessages = [];
45-
46-
// Ensure .json files are fingerprinted
47-
if (!fingerprintOptions.extensions) {
48-
// eslint-disable-next-line node/no-unpublished-require
49-
let opts = require('broccoli-asset-rev/lib/default-options');
50-
51-
let extensions = opts.extensions.slice().concat(['json']);
52-
53-
infoMessages.push(
54-
`set fingerprint.extensions = ${JSON.stringify(extensions)}`
55-
);
56-
} else if (!fingerprintOptions.extensions.includes('json')) {
57-
fingerprintOptions.extensions.push('json');
58-
infoMessages.push("added 'json' to fingerprint.extensions");
59-
}
60-
61-
if (app.project.findAddonByName('ember-cli-fastboot')) {
62-
// Ensure package.json is NOT fingerprinted (this is added by fastboot)
63-
let excluded = fingerprintOptions.exclude || [];
64-
fingerprintOptions.exclude = excluded;
65-
66-
if (!excluded.includes('package.json')) {
67-
excluded.push('package.json');
68-
infoMessages.push("added 'package.json' to fingerprint.exclude");
69-
}
70-
}
71-
72-
if (infoMessages.length > 0) {
73-
this.ui.writeLine('');
74-
this.ui.writeLine(
75-
'ember-l10n automatically adjusted the fingerprinting settings to work properly:'
76-
);
77-
infoMessages.forEach((message) => this.ui.writeLine(`* ${message}`));
78-
this.ui.writeLine('');
79-
}
80-
}
81-
},
82-
83-
_getTranslationsFolder() {
84-
return `${this.project.root}/translations`;
85-
},
865
};

0 commit comments

Comments
 (0)