Browse Source

Load all namespaces up-front (no indv. queries) (#2680)

* Move i18n app to settings (discoverability)

* Load all namespecas up-front (no indv. queries)
Jaco Greeff 4 years ago
parent
commit
f21ae871f3

+ 0 - 5
packages/apps/public/locales/en/index.json

@@ -1,15 +1,12 @@
 [
-  "app-123code.json",
   "app-accounts.json",
   "app-claims.json",
   "app-contracts.json",
   "app-council.json",
-  "app-dashboard.json",
   "app-democracy.json",
   "app-explorer.json",
   "app-extrinsics.json",
   "app-generic-asset.json",
-  "app-i18n.json",
   "app-js.json",
   "app-parachains.json",
   "app-settings.json",
@@ -23,9 +20,7 @@
   "apps-config.json",
   "apps-routing.json",
   "apps.json",
-  "react-api.json",
   "react-components.json",
-  "react-hooks.json",
   "react-params.json",
   "react-query.json",
   "react-signer.json"

+ 1 - 3
packages/apps/src/Content/index.tsx

@@ -78,15 +78,13 @@ function Content ({ className }: Props): React.ReactElement<Props> {
 
 export default React.memo(styled(Content)`
   background: #f5f5f5;
-  display: flex;
-  flex-direction: column;
   flex-grow: 1;
   height: 100%;
   min-height: 100vh;
   overflow-x: hidden;
   overflow-y: auto;
   width: 100%;
-  padding: 0 2rem;
+  padding: 0 1.5rem;
 
   @media(max-width: 768px) {
     padding: 0 0.5rem;

+ 27 - 10
packages/react-components/src/i18n/Backend.ts

@@ -6,26 +6,43 @@ import languageCache from './cache';
 
 type Callback = (error: string | null, data: any) => void;
 
+type LoadResult = [string | null, any];
+
+const loaders: Record<string, Promise<LoadResult>> = {};
+
 export default class Backend {
   type = 'backend'
 
   static type: 'backend' = 'backend'
 
   async read (lng: string, _namespace: string, responder: Callback): Promise<void> {
-    if (!languageCache[lng]) {
-      try {
-        const response = await fetch(`locales/${lng}/translation.json`, {});
+    if (languageCache[lng]) {
+      return responder(null, languageCache[lng]);
+    }
+
+    // eslint-disable-next-line @typescript-eslint/no-misused-promises
+    if (!loaders[lng]) {
+      loaders[lng] = this.createLoader(lng);
+    }
 
-        if (!response.ok) {
-          return responder(`i18n: failed loading ${lng}`, response.status >= 500 && response.status < 600);
-        }
+    const [error, data] = await loaders[lng];
 
+    return responder(error, data);
+  }
+
+  async createLoader (lng: string): Promise<LoadResult> {
+    try {
+      const response = await fetch(`locales/${lng}/translation.json`, {});
+
+      if (!response.ok) {
+        return [`i18n: failed loading ${lng}`, response.status >= 500 && response.status < 600];
+      } else {
         languageCache[lng] = await response.json();
-      } catch (error) {
-        return responder(error.message, false);
+
+        return [null, languageCache[lng]];
       }
+    } catch (error) {
+      return [error.message, false];
     }
-
-    return responder(null, languageCache[lng]);
   }
 }

+ 33 - 1
packages/react-components/src/i18n/index.ts

@@ -38,7 +38,39 @@ i18n
     },
     keySeparator: false,
     load: 'languageOnly',
-    ns: ['translation'],
+    ns: [
+      'apps',
+      'apps-config',
+      'apps-routing',
+      'app-123code',
+      'app-accounts',
+      'app-claims',
+      'app-contracts',
+      'app-council',
+      'app-dashboard',
+      'app-democracy',
+      'app-explorer',
+      'app-extrinsics',
+      'app-generic-asset',
+      'app-i18n',
+      'app-js',
+      'app-parachains',
+      'app-settings',
+      'app-society',
+      'app-staking',
+      'app-storage',
+      'app-sudo',
+      'app-tech-comm',
+      'app-toolbox',
+      'app-treasury',
+      'react-api',
+      'react-components',
+      'react-hooks',
+      'react-params',
+      'react-query',
+      'react-signer',
+      'translation'
+    ],
     nsSeparator: false,
     react: {
       wait: true

+ 10 - 1
scripts/i18nSort.js

@@ -7,6 +7,8 @@ const path = require('path');
 
 const i18nRoot = path.join(__dirname, '../packages/apps/public/locales');
 
+const SKIP_NS = ['app-123code', 'app-dashboard', 'app-i18n', 'translation'].map((f) => `${f}.json`);
+
 function getEntries (langRoot) {
   return fs
     .readdirSync(langRoot)
@@ -22,6 +24,7 @@ function getEntries (langRoot) {
 function sortLanguage (lang) {
   const langRoot = path.join(i18nRoot, lang);
   const entries = getEntries(langRoot);
+  const hasKeys = {};
 
   entries.forEach((entry) => {
     const filename = path.join(langRoot, entry);
@@ -32,13 +35,19 @@ function sortLanguage (lang) {
       return result;
     }, {});
 
+    hasKeys[entry] = Object.keys(sorted).length !== 0;
+
     fs.writeFileSync(filename, JSON.stringify(sorted, null, 2));
   });
 
   if (lang === 'en') {
+    const filtered = entries
+      .filter((entry) => !SKIP_NS.includes(entry))
+      .filter((entry) => hasKeys[entry]);
+
     fs.writeFileSync(
       path.join(langRoot, 'index.json'),
-      JSON.stringify(entries.filter((entry) => !['translation.json'].includes(entry)), null, 2)
+      JSON.stringify(filtered, null, 2)
     );
   }
 }