Skip to content

Commit

Permalink
feat(PWA): Add translations loader plugin
Browse files Browse the repository at this point in the history
(cherry picked from commit b1cc435)
  • Loading branch information
cogk authored and mergify[bot] committed Oct 23, 2024
1 parent 48d4996 commit d24ec2c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 8 deletions.
17 changes: 9 additions & 8 deletions frontend/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
resourcesPlugin,
FormControl,
} from "frappe-ui"
import { translationsPlugin } from "./plugins/translationsPlugin.js"
import EmptyState from "@/components/EmptyState.vue"

import { IonicVue } from "@ionic/vue"
Expand All @@ -37,6 +38,7 @@ const socket = initSocket()

setConfig("resourceFetcher", frappeRequest)
app.use(resourcesPlugin)
app.use(translationsPlugin)

app.component("Button", Button)
app.component("Input", Input)
Expand Down Expand Up @@ -91,20 +93,19 @@ const registerServiceWorker = async () => {
}
}

router.isReady().then(() => {
router.isReady().then(async () => {
if (import.meta.env.DEV) {
frappeRequest({
await frappeRequest({
url: "/api/method/hrms.www.hrms.get_context_for_dev",
}).then((values) => {
}).then(async (values) => {
if (!window.frappe) window.frappe = {}
window.frappe.boot = values
registerServiceWorker()
app.mount("#app")
})
} else {
registerServiceWorker()
app.mount("#app")
}

await translationsPlugin.isReady();
registerServiceWorker()
app.mount("#app")
})

router.beforeEach(async (to, _, next) => {
Expand Down
83 changes: 83 additions & 0 deletions frontend/src/plugins/translationsPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
function makeTranslationFunction() {
let messages = {};
return {
translate,
load: () => Promise.allSettled([
setup(),
setupDayjs(),
]),
}

async function setup() {
if (window.frappe?.boot?.__messages) {
messages = window.frappe?.boot?.__messages;
return;
}

const url = new URL("/api/method/frappe.translate.load_all_translations", location.origin);
url.searchParams.append("lang", window.frappe?.boot?.lang ?? navigator.language);
url.searchParams.append("hash", window.frappe?.boot?.translations_hash || window._version_number || Math.random()); // for cache busting
// url.searchParams.append("app", "hrms");

try {
const response = await fetch(url);
messages = await response.json() || {}
} catch (error) {
console.error("Failed to fetch translations:", error)
}
}

async function setupDayjs() {
// TODO
}

function translate(txt, replace, context = null) {
if (!txt || typeof txt != "string") return txt;

let translated_text = "";
let key = txt;
if (context) {
translated_text = messages[`${key}:${context}`];
}
if (!translated_text) {
translated_text = messages[key] || txt;
}
if (replace && typeof replace === "object") {
translated_text = format(translated_text, replace);
}

return translated_text;
}

function format(str, args) {
if (str == undefined) return str;

let unkeyed_index = 0;
return str.replace(
/\{(\w*)\}/g,
(match, key) => {
if (key === "") {
key = unkeyed_index;
unkeyed_index++;
}
if (key == +key) {
return args[key] !== undefined ? args[key] : match;
}
}
);
}
}

const { translate, load } = makeTranslationFunction();

export const translationsPlugin = {
async isReady() {
await load();
},
install(/** @type {import('vue').App} */ app, options) {
const __ = translate;
// app.mixin({ methods: { __ } })
app.config.globalProperties.__ = __;
app.provide("$translate", __);
},
}

0 comments on commit d24ec2c

Please sign in to comment.