Skip to content

Commit

Permalink
make languages a static Store class
Browse files Browse the repository at this point in the history
  • Loading branch information
amerharb committed Nov 27, 2023
1 parent 609ffe4 commit 08d7c20
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 4 deletions.
56 changes: 56 additions & 0 deletions webapp/src/app/api/Store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { envVarNotFound } from '@/utils/util';
import fs from 'fs/promises';
import { parse } from 'yaml';
import { simpleGit, SimpleGit, SimpleGitOptions } from 'simple-git';

const REPO_PATH = process.env.REPO_PATH ?? envVarNotFound('REPO_PATH');
const MAIN_BRANCH = 'main';

export class Store {
public static async getLanguage(lang: string) {
let languages: Map<string, Record<string, unknown>>;
if (!globalThis.languages) {
console.debug('Initializing languages');
const options: Partial<SimpleGitOptions> = {
baseDir: REPO_PATH,
binary: 'git',
maxConcurrentProcesses: 1,
trimmed: false,
};
const git: SimpleGit = simpleGit(options);
console.debug('git checkout main pull...');
await git.checkout(MAIN_BRANCH);
console.debug('git pull...');
await git.pull();
console.debug('git done checkout main branch and pull');
languages = new Map<string, Record<string, unknown>>();
globalThis.languages = languages;
} else {
console.debug('find languages in Memory');
languages = globalThis.languages;
}

let translations: Record<string, unknown>;
if (!languages.has(lang)) {
console.debug('read language[' + lang +'] from file');
// TODO: read this from .lyra.yml setting file in client repo
const yamlPath = REPO_PATH + `/src/locale/${lang}.yml`;

const yamlBuf = await fs.readFile(yamlPath);
// TODO: change parsing to be flattened map of key to value, instead of object
// so key will be like 'key1.key2.key3' and value will be 'translated text'
// this will reduce the cost of looping for the object every time we need to save a message
translations = parse(yamlBuf.toString()) as Record<string, unknown>;
languages.set(lang, translations);
} else {
console.debug('read language [' + lang + '] from Memory');
translations = languages.get(lang) ?? Store.throwLangNotFound(lang);
}

return translations;
}

private static throwLangNotFound(lang: string): never {
throw new Error(`Language ${lang} not found`);
}
}
4 changes: 4 additions & 0 deletions webapp/src/app/api/messages/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ const REPO_PATH = process.env.REPO_PATH ?? envVarNotFound('REPO_PATH');

export async function GET() {
const messages: MessageData[] = [];
// TODO: read path or src from .lyra.yml setting file in client repo
for await (const item of getMessageFiles(REPO_PATH + '/src')) {
messages.push(...readTypedMessages(item));
}

// TODO: change data instruction to be a map of key to value, instead of object
// message id is the key, and value is an object with default and params
// example: { 'key1.key2.key3': { default: 'default text', params: [] }}
return NextResponse.json({
data: messages,
});
Expand Down
1 change: 1 addition & 0 deletions webapp/src/app/api/pull-request/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export async function POST() {
const languages = globalThis.languages;
for (const lang of languages.keys()) {
const yamlPath = REPO_PATH + `/src/locale/${lang}.yml`;
// TODO: when language obj become a map of key to value, then it need to be converted to object before stringify
const yamlOutput = stringify(languages.get(lang), {
doubleQuotedAsJSON: true,
singleQuote: true,
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/app/api/translations/[lang]/[msgId]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getLanguage } from '@/app/api/languages';
import { Store } from '@/app/api/Store';
import { NextRequest, NextResponse } from 'next/server';

export async function PUT(
Expand All @@ -15,7 +15,7 @@ export async function PUT(
const { text } = payload;

const objKeyPath = msgId.split('.');
let curObj = await getLanguage(lang);
let curObj = await Store.getLanguage(lang);
objKeyPath.forEach((key, index) => {
if (index == objKeyPath.length - 1) {
curObj[key] = text;
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/app/api/translations/[lang]/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { getLanguage } from '@/app/api/languages';
import { Store } from '@/app/api/Store';
import { NextRequest, NextResponse } from 'next/server';

export async function GET(
req: NextRequest, // keep this here even if unused
context: { params: { lang: string; msgId: string } },
) {
const lang = context.params.lang;
const langObj = await getLanguage(lang);
const langObj = await Store.getLanguage(lang);
const flattenLangObj = flattenObject(langObj);

return NextResponse.json({
Expand Down

0 comments on commit 08d7c20

Please sign in to comment.