Skip to content

Commit 0df55aa

Browse files
committed
Add more commands to translatte
- Add command to export server strings - Add command to push migration to the server - Add command to clear strings from the server
1 parent 102aa66 commit 0df55aa

File tree

8 files changed

+747
-3
lines changed

8 files changed

+747
-3
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { listToGroupList } from "@togglecorp/fujs";
2+
import { fetchServerState, postLanguageStrings, writeFilePromisify } from "../utils";
3+
4+
async function clearServerStrings(apiUrl: string, authToken: string) {
5+
const serverStrings = await fetchServerState(apiUrl, authToken);
6+
7+
const bulkActions = listToGroupList(
8+
serverStrings,
9+
({ language }) => language,
10+
({ key, page_name }) => ({
11+
action: "delete" as const,
12+
key,
13+
page_name,
14+
}),
15+
);
16+
17+
const logs: {
18+
responseFor: string,
19+
response: object,
20+
}[] = [];
21+
22+
console.log('Pusing delete actions for en...')
23+
const enResponse = await postLanguageStrings(
24+
'en',
25+
bulkActions.en,
26+
apiUrl,
27+
authToken,
28+
);
29+
30+
const enResponseJson = await enResponse.json();
31+
logs.push({ responseFor: 'en', response: enResponseJson });
32+
33+
34+
console.log('Pusing delete actions for fr...')
35+
const frResponse = await postLanguageStrings(
36+
'fr',
37+
bulkActions.fr,
38+
apiUrl,
39+
authToken,
40+
);
41+
42+
const frResponseJson = await frResponse.json();
43+
logs.push({ responseFor: 'fr', response: frResponseJson });
44+
45+
console.log('Pusing delete actions for es...')
46+
const esResponse = await postLanguageStrings(
47+
'es',
48+
bulkActions.es,
49+
apiUrl,
50+
authToken,
51+
);
52+
const esResponseJson = await esResponse.json();
53+
logs.push({ responseFor: 'es', response: esResponseJson });
54+
55+
console.log('Pusing delete actions for ar...')
56+
const arResponse = await postLanguageStrings(
57+
'ar',
58+
bulkActions.ar,
59+
apiUrl,
60+
authToken,
61+
);
62+
63+
const arResponseJson = await arResponse.json();
64+
logs.push({ responseFor: 'ar', response: arResponseJson });
65+
66+
await writeFilePromisify(
67+
'clear-server-strings-log.json',
68+
JSON.stringify(logs, null, 2),
69+
'utf8',
70+
);
71+
}
72+
73+
export default clearServerStrings;

app/scripts/translatte/commands/exportMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ async function exportMigration(
5353
});
5454

5555
const fileName = isNotDefined(exportFileName)
56-
? `go-strings-${yyyy}-${mm}-${dd}`
56+
? `go-migration-strings-${yyyy}-${mm}-${dd}`
5757
: exportFileName;
5858

5959
await workbook.xlsx.writeFile(`${fileName}.xlsx`);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import xlsx from 'exceljs';
2+
3+
import { fetchServerState } from "../utils";
4+
import { isFalsyString, listToGroupList, listToMap, mapToList } from '@togglecorp/fujs';
5+
6+
async function exportServerStringsToExcel(
7+
apiUrl: string,
8+
authToken?: string,
9+
exportFileName?: string,
10+
) {
11+
const serverStrings = await fetchServerState(apiUrl, authToken);
12+
13+
const workbook = new xlsx.Workbook();
14+
const now = new Date();
15+
workbook.created = now;
16+
17+
const yyyy = now.getFullYear();
18+
const mm = (now.getMonth() + 1).toString().padStart(2, '0');
19+
const dd = now.getDate().toString().padStart(2, '0');
20+
const HH = now.getHours().toString().padStart(2, '0');
21+
const MM = now.getMinutes().toString().padStart(2, '0');
22+
23+
const worksheet = workbook.addWorksheet(
24+
`${yyyy}-${mm}-${dd} ${HH}-${MM}`
25+
);
26+
27+
worksheet.columns = [
28+
{ header: 'Namespace', key: 'namespace' },
29+
{ header: 'Key', key: 'key' },
30+
{ header: 'EN', key: 'en' },
31+
{ header: 'FR', key: 'fr' },
32+
{ header: 'ES', key: 'es' },
33+
{ header: 'AR', key: 'ar' },
34+
]
35+
36+
const keyGroupedStrings = mapToList(
37+
listToGroupList(
38+
serverStrings,
39+
({ page_name, key }) => `${page_name}:${key}`,
40+
),
41+
(list) => {
42+
const value = listToMap(
43+
list,
44+
({ language }) => language,
45+
({ value }) => value
46+
);
47+
const hash = listToMap(
48+
list,
49+
({ language }) => language,
50+
({ hash }) => hash,
51+
);
52+
const { key, page_name } = list[0];
53+
54+
return {
55+
namespace: page_name,
56+
key: key,
57+
en: value.en,
58+
fr: hash.fr === hash.en ? value.fr : undefined,
59+
es: hash.es === hash.en ? value.es : undefined,
60+
ar: hash.ar === hash.en ? value.ar : undefined,
61+
};
62+
},
63+
);
64+
65+
Object.values(keyGroupedStrings).forEach((keyGroupedString) => {
66+
worksheet.addRow(keyGroupedString);
67+
});
68+
69+
const fileName = isFalsyString(exportFileName)
70+
? `go-server-strings-${yyyy}-${mm}-${dd}`
71+
: exportFileName;
72+
73+
await workbook.xlsx.writeFile(`${fileName}.xlsx`);
74+
}
75+
76+
export default exportServerStringsToExcel;
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import { isDefined, isFalsyString, isNotDefined, listToGroupList, listToMap, mapToMap } from "@togglecorp/fujs";
2+
import { Language, MigrationActionItem, ServerActionItem } from "../types";
3+
import { fetchServerState, getCombinedKey, languages, postLanguageStrings, readMigrations, writeFilePromisify } from "../utils";
4+
import { Md5 } from "ts-md5";
5+
6+
async function pushMigration(migrationFilePath: string, apiUrl: string, authToken: string) {
7+
const serverStrings = await fetchServerState(apiUrl, authToken);
8+
9+
const serverStringMapByCombinedKey = mapToMap(
10+
listToGroupList(
11+
serverStrings,
12+
({ key, page_name }) => getCombinedKey(key, page_name),
13+
),
14+
(key) => key,
15+
(list) => listToMap(
16+
list,
17+
({ language }) => language,
18+
)
19+
);
20+
21+
const migrations = await readMigrations(
22+
[migrationFilePath]
23+
);
24+
25+
const actions = migrations[0].content.actions;
26+
27+
28+
function getItemsForNamespaceUpdate(actionItem: MigrationActionItem, language: Language) {
29+
if (actionItem.action !== 'update') {
30+
return undefined;
31+
}
32+
33+
if (isNotDefined(actionItem.newNamespace)) {
34+
return undefined;
35+
}
36+
37+
const oldCombinedKey = getCombinedKey(
38+
actionItem.key,
39+
actionItem.namespace,
40+
);
41+
42+
const oldStringItem = serverStringMapByCombinedKey[oldCombinedKey]?.[language];
43+
44+
if (isNotDefined(oldStringItem) || isFalsyString(oldStringItem.value)) {
45+
return undefined;
46+
}
47+
48+
return [
49+
{
50+
action: 'delete' as const,
51+
key: actionItem.key,
52+
page_name: actionItem.namespace,
53+
},
54+
{
55+
action: 'set' as const,
56+
key: actionItem.key,
57+
page_name: actionItem.newNamespace,
58+
value: oldStringItem.value,
59+
hash: oldStringItem.hash,
60+
},
61+
];
62+
}
63+
64+
function getItemsForKeyUpdate(actionItem: MigrationActionItem, language: Language) {
65+
if (actionItem.action !== 'update') {
66+
return undefined;
67+
}
68+
69+
if (isNotDefined(actionItem.newKey)) {
70+
return undefined;
71+
}
72+
73+
const oldCombinedKey = getCombinedKey(
74+
actionItem.key,
75+
actionItem.namespace,
76+
);
77+
78+
const oldStringItem = serverStringMapByCombinedKey[oldCombinedKey]?.[language];
79+
80+
if (isNotDefined(oldStringItem) || isFalsyString(oldStringItem.value)) {
81+
return undefined;
82+
}
83+
84+
return [
85+
{
86+
action: 'delete' as const,
87+
key: actionItem.key,
88+
page_name: actionItem.namespace,
89+
},
90+
{
91+
action: 'set' as const,
92+
key: actionItem.newKey,
93+
page_name: actionItem.namespace,
94+
value: oldStringItem.value,
95+
hash: oldStringItem.hash,
96+
},
97+
];
98+
}
99+
100+
const serverActions = listToMap(
101+
languages.map((language) => {
102+
const serverActionsForCurrentLanguage = actions.flatMap((actionItem) => {
103+
if (language === 'en') {
104+
if (actionItem.action === 'add') {
105+
return {
106+
action: 'set' as const,
107+
key: actionItem.key,
108+
page_name: actionItem.namespace,
109+
value: actionItem.value,
110+
hash: Md5.hashStr(actionItem.value),
111+
}
112+
}
113+
114+
if (actionItem.action === 'remove') {
115+
return {
116+
action: 'delete' as const,
117+
key: actionItem.key,
118+
page_name: actionItem.namespace,
119+
}
120+
}
121+
122+
if (isDefined(actionItem.newNamespace)) {
123+
return getItemsForNamespaceUpdate(actionItem, language);
124+
}
125+
126+
if (isDefined(actionItem.newKey)) {
127+
return getItemsForKeyUpdate(actionItem, language);
128+
}
129+
130+
if (isDefined(actionItem.newValue)) {
131+
return {
132+
action: 'set' as const,
133+
key: actionItem.key,
134+
page_name: actionItem.namespace,
135+
value: actionItem.newValue,
136+
hash: Md5.hashStr(actionItem.newValue),
137+
}
138+
}
139+
} else {
140+
if (actionItem.action === 'remove') {
141+
return {
142+
action: 'delete' as const,
143+
key: actionItem.key,
144+
page_name: actionItem.namespace,
145+
}
146+
}
147+
148+
if (actionItem.action === 'update') {
149+
if (isDefined(actionItem.newNamespace)) {
150+
return getItemsForNamespaceUpdate(actionItem, language);
151+
}
152+
153+
if (isDefined(actionItem.newKey)) {
154+
return getItemsForKeyUpdate(actionItem, language);
155+
}
156+
}
157+
}
158+
159+
return undefined;
160+
}).filter(isDefined);
161+
162+
return {
163+
language,
164+
actions: serverActionsForCurrentLanguage,
165+
}
166+
}),
167+
({ language }) => language,
168+
);
169+
170+
await writeFilePromisify(
171+
`server-actions.json`,
172+
JSON.stringify(serverActions, null, 2),
173+
'utf8',
174+
);
175+
176+
const logs: {
177+
responseFor: string,
178+
response: object,
179+
}[] = [];
180+
181+
async function applyAction(lang: Language, actions: ServerActionItem[]) {
182+
console.log(`Pusing actions for ${lang}...`)
183+
const response = await postLanguageStrings(
184+
lang,
185+
actions,
186+
apiUrl,
187+
authToken,
188+
);
189+
const responseJson = await response.json();
190+
logs.push({ responseFor: 'en', response: responseJson });
191+
192+
/*
193+
const setActions = actions.filter(({ action }) => action === 'set');
194+
const deleteActions = actions.filter(({ action }) => action === 'delete');
195+
196+
console.log(`Pusing deleted actions for ${lang}...`)
197+
const deleteResponse = await postLanguageStrings(
198+
lang,
199+
deleteActions,
200+
apiUrl,
201+
authToken,
202+
);
203+
const deleteResponseJson = await deleteResponse.json();
204+
logs.push({ responseFor: 'delete en', response: deleteResponseJson });
205+
206+
console.log(`Pusing set actions for ${lang}...`)
207+
const setResponse = await postLanguageStrings(
208+
lang,
209+
setActions,
210+
apiUrl,
211+
authToken,
212+
);
213+
const setResponseJson = await setResponse.json();
214+
logs.push({ responseFor: 'set en', response: setResponseJson });
215+
*/
216+
}
217+
218+
await applyAction(serverActions.en.language, serverActions.en.actions);
219+
await applyAction(serverActions.fr.language, serverActions.fr.actions);
220+
await applyAction(serverActions.es.language, serverActions.es.actions);
221+
await applyAction(serverActions.ar.language, serverActions.ar.actions);
222+
223+
await writeFilePromisify(
224+
`push-migration-logs.json`,
225+
JSON.stringify(logs, null, 2),
226+
'utf8',
227+
);
228+
}
229+
230+
export default pushMigration;

0 commit comments

Comments
 (0)