Skip to content

Commit

Permalink
feat: add simplelocalize.io
Browse files Browse the repository at this point in the history
  • Loading branch information
GalvinGao committed Feb 17, 2023
1 parent 9a1fcfb commit e115dc7
Show file tree
Hide file tree
Showing 11 changed files with 323 additions and 20 deletions.
8 changes: 4 additions & 4 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.9.3;
MARKETING_VERSION = 3.10.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.penguinstats.app.PenguinWidget;
Expand Down Expand Up @@ -751,7 +751,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.9.3;
MARKETING_VERSION = 3.10.4;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.penguinstats.app.PenguinWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -949,7 +949,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.9.3;
MARKETING_VERSION = 3.10.4;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = io.penguinstats.app;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -981,7 +981,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.9.3;
MARKETING_VERSION = 3.10.4;
PRODUCT_BUNDLE_IDENTIFIER = io.penguinstats.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = NO;
Expand Down
2 changes: 1 addition & 1 deletion ios/App/Settings.bundle/Root.plist
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<array>
<dict>
<key>DefaultValue</key>
<string>3.9.3 (0)</string>
<string>3.10.4 (0)</string>
<key>Key</key>
<string>version</string>
<key>Title</key>
Expand Down
6 changes: 1 addition & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^6.2.2",
"eslint-plugin-vuetify": "^1.0.0-beta.5",
"esno": "^0.16.3",
"husky": "^4.2.5",
"js-yaml-loader": "^1.2.2",
"raw-loader": "^4.0.2",
Expand Down Expand Up @@ -124,11 +125,6 @@
"bugs": {
"url": "https://github.com/penguin-statistics/frontend-v2/issues"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"contributors": [
"AlvISs_Reimu <alvissreimu@gmail.com> (https://github.com/AlvISsReimu)",
"Galvin Gao <me@galvingao.com> (https://github.com/GalvinGao)",
Expand Down
1 change: 1 addition & 0 deletions src/locales/en.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/locales/ja.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/locales/ko.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/locales/zh.json

Large diffs are not rendered by default.

112 changes: 104 additions & 8 deletions src/mixins/I18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,113 @@ import dayjs from 'dayjs'
import Console from '@/utils/Console'
import { mapGetters } from 'vuex'
import helmet from "@/utils/helmet";
import { service } from '../utils/service';
import i18n from '../i18n';

const fetchTranslations = async (languageKey) => {
const projectPublishableToken = "52e5ff4b225147a9b11bb63865b2ae1f";
const environment = "_production"; // or '_production'
const url = `https://cdn.simplelocalize.io/${projectPublishableToken}/${environment}/${languageKey}`;
return fetch(url).then((data) => {
if (!data.ok || data.status !== 200) {
throw new Error(data.statusText);
}
return data.json();
});
};

const loadedLanguages = [];

const languageMapping = {
en: "en",
zh: "zh_CN",
ja: "ja_JP",
ko: "ko_KR",
}

function changeLocale (localeId, save) {
dayjs.locale(localeId);
Console.info("i18n", "locale:", localeId, "| saving to vuex:", save);
if (save) this.$store.commit("settings/changeLocale", localeId);
service.defaults.headers.common["Accept-Language"] = localeId;
this.$i18n.locale = localeId;
this.$vuetify.lang.current = localeId;
helmet.title.update(this.$route);
document.documentElement.lang = localeId;
}

// messages are in the form of Record<string, string>.
// if the key of the message contains `path1.path2`, it should be converted to a corresponding object
// similarly, if the key of the message contains `path1.path2[number]`, it should be converted to a corresponding object with an array
// e.g. { 'path1.path2': 'value', 'path1.path3[0]': 'value1', 'path1.path3[1]': 'value2' } should be converted to { path1: { path2: 'value', path3: ['value1', 'value2'] } }
function transformMessages (messages) {
const transformedMessages = {};
Object.keys(messages).forEach((key) => {
const path = key.split('.');
let current = transformedMessages;
for (let i = 0; i < path.length; i++) {
const pathPart = path[i];
if (pathPart.endsWith(']')) {
// array
const arrayPath = pathPart.split('[');
const arrayName = arrayPath[0];
const arrayIndex = parseInt(arrayPath[1].replace(']', ''));
if (!current[arrayName]) {
current[arrayName] = [];
}
if (i === path.length - 1) {
current[arrayName][arrayIndex] = messages[key];
} else {
if (!current[arrayName][arrayIndex]) {
current[arrayName][arrayIndex] = {};
}
current = current[arrayName][arrayIndex];
}
} else {
// object
if (i === path.length - 1) {
current[pathPart] = messages[key];
} else {
if (!current[pathPart]) {
current[pathPart] = {};
}
current = current[pathPart];
}
}
}
});
return transformedMessages;
}

export function loadLanguageAsync(lang) {
// If the same language
if (i18n.locale === lang) return Promise.resolve();

const mappedLang = languageMapping[lang] || lang;

// If the language was already loaded
if (loadedLanguages.includes(mappedLang)) return Promise.resolve();

// If the language hasn't been loaded yet
// set it first to use the local translation
changeLocale.bind(this)(lang, false);

return fetchTranslations(mappedLang).then((messages) => {
const transformedMessages = Object.freeze(transformMessages(messages));
Console.info("i18n", "loaded", lang, "translations:", transformedMessages);
i18n.setLocaleMessage(lang, transformedMessages);
loadedLanguages.push(mappedLang);

return Promise.resolve();
});
}

export default {
methods: {
changeLocale (localeId, save = true) {
dayjs.locale(localeId)
Console.info('i18n', 'locale:', localeId, '| saving to vuex:', save)
if (save) this.$store.commit('settings/changeLocale', localeId)
this.$i18n.locale = localeId
this.$vuetify.lang.current = localeId
helmet.title.update(this.$route)
document.documentElement.lang = localeId
async changeLocale (localeId, save = true) {
await loadLanguageAsync.bind(this)(localeId)

changeLocale.bind(this)(localeId, save);
}
},
computed: {
Expand Down
23 changes: 23 additions & 0 deletions src/scripts/locales-to-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import fs from "fs/promises";

async function main() {
const locales = await fs.readdir("./src/locales");

const messages = await Promise.all(
locales
.filter((el) => el.endsWith(".js"))
.map(async (locale) => ({
locale: locale.replace(".js", ""),
messages: await import(`../locales/${locale}`),
}))
);

messages.forEach((locale) => {
fs.writeFile(
`./src/locales/${locale.locale}.json`,
JSON.stringify(locale.messages.default)
);
});
}

main();
1 change: 0 additions & 1 deletion src/views/About/Intro.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@
rel="noopener"
class="mr-1"
text
v-on="on"
>
<div class="d-flex align-center justify-content-center ">
<v-icon left>
Expand Down
Loading

0 comments on commit e115dc7

Please sign in to comment.