Skip to content

Commit cff8b43

Browse files
committed
Load locales on app init based on the user's browser
1 parent e503826 commit cff8b43

File tree

4 files changed

+163
-13
lines changed

4 files changed

+163
-13
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"author": "Emmanuel Vilsbol <emmanuel@vilsbol.com>",
33
"dependencies": {
44
"@fluent/bundle": "^0.16.0",
5+
"@fluent/langneg": "^0.5.0",
56
"@vue/composition-api": "^1.0.0-rc.6",
67
"axios": "^0.19.0",
78
"date-fns": "^1.30.1",

src/common/fluent-utils.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { FluentBundle, FluentResource } from "@fluent/bundle";
2+
import { negotiateLanguages } from "@fluent/langneg";
3+
import { createFluentVue } from "fluent-vue";
4+
5+
const DEFAULT_LOCALE = "en-US";
6+
const SUPPORTED_LOCALES = ["en-US", "pt-BR"];
7+
8+
function getDesiredLocales(maxLanguages) {
9+
const desired = negotiateLanguages(navigator.languages, SUPPORTED_LOCALES, {
10+
defaultLocale: DEFAULT_LOCALE,
11+
strategy: "matching"
12+
});
13+
14+
const allowed = [];
15+
let previous = null;
16+
let count = -1;
17+
for (const locale of desired) {
18+
const lang = locale.substr(0, 2);
19+
20+
if (previous != lang) {
21+
previous = lang;
22+
count += 1;
23+
}
24+
25+
if (count >= maxLanguages) {
26+
break;
27+
}
28+
29+
allowed.push(locale);
30+
}
31+
32+
if (!allowed.includes(DEFAULT_LOCALE)) {
33+
allowed.push(DEFAULT_LOCALE);
34+
}
35+
36+
return allowed;
37+
}
38+
39+
async function loadCatalog(locale, catalogName) {
40+
try {
41+
const { default: contents } = await import(
42+
`../locales/${locale}/${catalogName}.ftl`
43+
);
44+
return contents;
45+
} catch (err) {
46+
console.warn(`Could not load catalog ${locale}/${catalogName}`);
47+
return "";
48+
}
49+
}
50+
51+
async function loadAndCreateFluentVue(maxLanguages = 1) {
52+
return Promise.all(
53+
getDesiredLocales(maxLanguages).map(locale =>
54+
loadCatalog(locale, "global").then(data => ({ locale, data }))
55+
)
56+
).then(catalogsData => {
57+
const bundles = catalogsData.map(({ locale, data }) => {
58+
const bundle = new FluentBundle(locale);
59+
const errors = bundle.addResource(new FluentResource(data));
60+
61+
if (errors.length > 0) {
62+
console.warn(`Errors loading fluent resource ${locale}/global`, errors);
63+
}
64+
65+
return bundle;
66+
});
67+
68+
return createFluentVue({
69+
locale: catalogsData.map(({ locale }) => locale),
70+
bundles: bundles
71+
});
72+
});
73+
}
74+
75+
export { DEFAULT_LOCALE, SUPPORTED_LOCALES, loadAndCreateFluentVue };

src/main.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Vue from "vue";
2+
23
import App from "./App.vue";
34
import router from "./router";
45
import store from "./store";
@@ -8,20 +9,25 @@ import { CHECK_AUTH } from "./store/actions.type";
89
import ApiService from "./common/api.service";
910
import DateFilter from "./common/date.filter";
1011
import ErrorFilter from "./common/error.filter";
12+
import { loadAndCreateFluentVue } from "./common/fluent-utils";
13+
14+
loadAndCreateFluentVue().then(fluent => {
15+
Vue.use(fluent);
1116

12-
Vue.config.productionTip = false;
13-
Vue.filter("date", DateFilter);
14-
Vue.filter("error", ErrorFilter);
17+
Vue.config.productionTip = false;
18+
Vue.filter("date", DateFilter);
19+
Vue.filter("error", ErrorFilter);
1520

16-
ApiService.init();
21+
ApiService.init();
1722

18-
// Ensure we checked auth before each page load.
19-
router.beforeEach((to, from, next) =>
20-
Promise.all([store.dispatch(CHECK_AUTH)]).then(next)
21-
);
23+
// Ensure we checked auth before each page load.
24+
router.beforeEach((to, from, next) =>
25+
Promise.all([store.dispatch(CHECK_AUTH)]).then(next)
26+
);
2227

23-
new Vue({
24-
router,
25-
store,
26-
render: h => h(App)
27-
}).$mount("#app");
28+
new Vue({
29+
router,
30+
store,
31+
render: h => h(App)
32+
}).$mount("#app");
33+
});

yarn.lock

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,11 @@
981981
"@types/istanbul-lib-coverage" "*"
982982
"@types/istanbul-lib-report" "*"
983983

984+
"@types/json-schema@^7.0.6":
985+
version "7.0.7"
986+
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
987+
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
988+
984989
"@types/minimatch@*":
985990
version "3.0.3"
986991
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -1523,6 +1528,11 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
15231528
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
15241529
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
15251530

1531+
ajv-keywords@^3.5.2:
1532+
version "3.5.2"
1533+
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
1534+
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
1535+
15261536
ajv@^5.2.3, ajv@^5.3.0:
15271537
version "5.5.2"
15281538
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
@@ -1543,6 +1553,16 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5:
15431553
json-schema-traverse "^0.4.1"
15441554
uri-js "^4.2.2"
15451555

1556+
ajv@^6.12.5:
1557+
version "6.12.6"
1558+
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
1559+
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
1560+
dependencies:
1561+
fast-deep-equal "^3.1.1"
1562+
fast-json-stable-stringify "^2.0.0"
1563+
json-schema-traverse "^0.4.1"
1564+
uri-js "^4.2.2"
1565+
15461566
alphanum-sort@^1.0.0:
15471567
version "1.0.2"
15481568
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
@@ -3809,6 +3829,11 @@ emojis-list@^2.0.0:
38093829
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
38103830
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
38113831

3832+
emojis-list@^3.0.0:
3833+
version "3.0.0"
3834+
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
3835+
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
3836+
38123837
encodeurl@~1.0.2:
38133838
version "1.0.2"
38143839
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@@ -4314,6 +4339,11 @@ fast-deep-equal@^2.0.1:
43144339
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
43154340
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
43164341

4342+
fast-deep-equal@^3.1.1:
4343+
version "3.1.3"
4344+
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
4345+
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
4346+
43174347
fast-diff@^1.1.2:
43184348
version "1.2.0"
43194349
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
@@ -6541,6 +6571,13 @@ json5@^2.1.0:
65416571
dependencies:
65426572
minimist "^1.2.0"
65436573

6574+
json5@^2.1.2:
6575+
version "2.2.0"
6576+
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
6577+
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
6578+
dependencies:
6579+
minimist "^1.2.5"
6580+
65446581
jsonfile@^4.0.0:
65456582
version "4.0.0"
65466583
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -6776,6 +6813,15 @@ loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2
67766813
emojis-list "^2.0.0"
67776814
json5 "^1.0.1"
67786815

6816+
loader-utils@^2.0.0:
6817+
version "2.0.0"
6818+
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
6819+
integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
6820+
dependencies:
6821+
big.js "^5.2.2"
6822+
emojis-list "^3.0.0"
6823+
json5 "^2.1.2"
6824+
67796825
locate-path@^2.0.0:
67806826
version "2.0.0"
67816827
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -7206,6 +7252,11 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
72067252
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
72077253
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
72087254

7255+
minimist@^1.2.5:
7256+
version "1.2.5"
7257+
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
7258+
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
7259+
72097260
minimist@~0.0.1:
72107261
version "0.0.10"
72117262
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
@@ -8862,6 +8913,14 @@ raw-body@2.4.0:
88628913
iconv-lite "0.4.24"
88638914
unpipe "1.0.0"
88648915

8916+
raw-loader@^4.0.2:
8917+
version "4.0.2"
8918+
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6"
8919+
integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==
8920+
dependencies:
8921+
loader-utils "^2.0.0"
8922+
schema-utils "^3.0.0"
8923+
88658924
rc@^1.2.7:
88668925
version "1.2.8"
88678926
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -9401,6 +9460,15 @@ schema-utils@^1.0.0:
94019460
ajv-errors "^1.0.0"
94029461
ajv-keywords "^3.1.0"
94039462

9463+
schema-utils@^3.0.0:
9464+
version "3.0.0"
9465+
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
9466+
integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
9467+
dependencies:
9468+
"@types/json-schema" "^7.0.6"
9469+
ajv "^6.12.5"
9470+
ajv-keywords "^3.5.2"
9471+
94049472
scss-tokenizer@^0.2.3:
94059473
version "0.2.3"
94069474
resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"

0 commit comments

Comments
 (0)