Explorar o código

Move to ui package

Manav Rathi hai 1 ano
pai
achega
fd3341f699

+ 1 - 1
apps/accounts/src/pages/_app.tsx

@@ -10,7 +10,7 @@ import {
 import EnteSpinner from '@ente/shared/components/EnteSpinner';
 import EnteSpinner from '@ente/shared/components/EnteSpinner';
 import AppNavbar from '@ente/shared/components/Navbar/app';
 import AppNavbar from '@ente/shared/components/Navbar/app';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
-import { setupI18n } from '@ente/shared/i18n';
+import { setupI18n } from '@/ui/i18n';
 import HTTPService from '@ente/shared/network/HTTPService';
 import HTTPService from '@ente/shared/network/HTTPService';
 import { LS_KEYS, getData } from '@ente/shared/storage/localStorage';
 import { LS_KEYS, getData } from '@ente/shared/storage/localStorage';
 import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
 import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';

+ 1 - 1
apps/auth/src/pages/_app.tsx

@@ -32,7 +32,7 @@ import { EnteAppProps } from '@ente/shared/apps/types';
 import createEmotionCache from '@ente/shared/themes/createEmotionCache';
 import createEmotionCache from '@ente/shared/themes/createEmotionCache';
 import { THEME_COLOR } from '@ente/shared/themes/constants';
 import { THEME_COLOR } from '@ente/shared/themes/constants';
 import { SetTheme } from '@ente/shared/themes/types';
 import { SetTheme } from '@ente/shared/themes/types';
-import { setupI18n } from '@ente/shared/i18n';
+import { setupI18n } from '@/ui/i18n';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { getTheme } from '@ente/shared/themes';
 import { getTheme } from '@ente/shared/themes';

+ 1 - 1
apps/photos/src/components/Sidebar/Preferences/LanguageSelector.tsx

@@ -2,7 +2,7 @@ import DropdownInput, { DropdownOption } from 'components/DropdownInput';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { t } from 'i18next';
 import { t } from 'i18next';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
-import { Language, getBestPossibleUserLocale } from '@ente/shared/i18n';
+import { Language, getBestPossibleUserLocale } from '@/ui/i18n';
 import { LS_KEYS } from '@ente/shared/storage/localStorage';
 import { LS_KEYS } from '@ente/shared/storage/localStorage';
 import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
 import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
 
 

+ 1 - 1
apps/photos/src/pages/_app.tsx

@@ -74,7 +74,7 @@ import { EnteAppProps } from '@ente/shared/apps/types';
 import createEmotionCache from '@ente/shared/themes/createEmotionCache';
 import createEmotionCache from '@ente/shared/themes/createEmotionCache';
 import { THEME_COLOR } from '@ente/shared/themes/constants';
 import { THEME_COLOR } from '@ente/shared/themes/constants';
 import { SetTheme } from '@ente/shared/themes/types';
 import { SetTheme } from '@ente/shared/themes/types';
-import { setupI18n } from '@ente/shared/i18n';
+import { setupI18n } from '@/ui/i18n';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { getTheme } from '@ente/shared/themes';
 import { getTheme } from '@ente/shared/themes';

+ 45 - 53
packages/shared/i18n/index.ts → packages/ui/i18n.ts

@@ -1,8 +1,9 @@
-import i18n from 'i18next';
-import { initReactI18next } from 'react-i18next';
-import Backend from 'i18next-http-backend';
-import { isDevBuild } from '@/utils/env';
-import { getUserLocales } from 'get-user-locale';
+import i18n from "i18next";
+import { initReactI18next } from "react-i18next";
+import Backend from "i18next-http-backend";
+import { isDevBuild } from "@/utils/env";
+import { getUserLocales } from "get-user-locale";
+import { includes } from "@/utils/type-guards";
 
 
 /**
 /**
  * Load translations.
  * Load translations.
@@ -32,7 +33,7 @@ export const setupI18n = async (savedLocaleString?: string) => {
         .init({
         .init({
             debug: isDevBuild,
             debug: isDevBuild,
             returnEmptyString: false,
             returnEmptyString: false,
-            fallbackLng: 'en',
+            fallbackLng: "en",
             lng: lng,
             lng: lng,
             interpolation: {
             interpolation: {
                 escapeValue: false, // not needed for react as it escapes by default
                 escapeValue: false, // not needed for react as it escapes by default
@@ -40,23 +41,23 @@ export const setupI18n = async (savedLocaleString?: string) => {
             react: {
             react: {
                 useSuspense: false,
                 useSuspense: false,
                 transKeepBasicHtmlNodesFor: [
                 transKeepBasicHtmlNodesFor: [
-                    'div',
-                    'strong',
-                    'h2',
-                    'span',
-                    'code',
-                    'p',
-                    'br',
+                    "div",
+                    "strong",
+                    "h2",
+                    "span",
+                    "code",
+                    "p",
+                    "br",
                 ],
                 ],
             },
             },
-            load: 'languageOnly',
+            load: "languageOnly",
         });
         });
 
 
-    i18n.services.formatter.add('dateTime', (value, lng) => {
+    i18n.services.formatter?.add("dateTime", (value, lng) => {
         return new Date(value / 1000).toLocaleDateString(lng, {
         return new Date(value / 1000).toLocaleDateString(lng, {
-            year: 'numeric',
-            month: 'long',
-            day: 'numeric',
+            year: "numeric",
+            month: "long",
+            day: "numeric",
         });
         });
     });
     });
 };
 };
@@ -71,29 +72,19 @@ export const setupI18n = async (savedLocaleString?: string) => {
  * few languages. When a translation reaches a high enough coverage, say 90%,
  * few languages. When a translation reaches a high enough coverage, say 90%,
  * then we manually add it to this list of supported languages.
  * then we manually add it to this list of supported languages.
  */
  */
-export type SupportedLocale = 'en' | 'fr' | 'zh' | 'nl' | 'es';
+export type SupportedLocale = "en" | "fr" | "zh" | "nl" | "es";
 
 
 /**
 /**
  * List of all {@link SupportedLocale}s.
  * List of all {@link SupportedLocale}s.
  */
  */
 export const supportedLocales: SupportedLocale[] = [
 export const supportedLocales: SupportedLocale[] = [
-    'en',
-    'fr',
-    'zh',
-    'nl',
-    'es',
+    "en",
+    "fr",
+    "zh",
+    "nl",
+    "es",
 ];
 ];
 
 
-/**
- * A type guard that returns true if the given string is a
- * {@link SupportedLocale}.
- */
-export const isSupportedLocale = (s: string): s is SupportedLocale => {
-    // The `as any` here is needed to work around current TS limitations
-    // https://github.com/microsoft/TypeScript/issues/48247
-    return supportedLocales.includes(s as any);
-};
-
 /**
 /**
  * Return the current locale in which our user interface is being shown.
  * Return the current locale in which our user interface is being shown.
  *
  *
@@ -103,44 +94,45 @@ export const isSupportedLocale = (s: string): s is SupportedLocale => {
  */
  */
 export const currentLocale = () => {
 export const currentLocale = () => {
     const locale = i18n.resolvedLanguage;
     const locale = i18n.resolvedLanguage;
-    return isSupportedLocale(locale) ? locale : 'en';
+    return locale && includes(supportedLocales, locale) ? locale : "en";
 };
 };
 
 
 /** Enums of supported locale */
 /** Enums of supported locale */
 export enum Language {
 export enum Language {
-    en = 'en',
-    fr = 'fr',
-    zh = 'zh',
-    nl = 'nl',
-    es = 'es',
+    en = "en",
+    fr = "fr",
+    zh = "zh",
+    nl = "nl",
+    es = "es",
 }
 }
 
 
-export function getBestPossibleUserLocale(savedLocaleString: string): Language {
-    const locale = savedLocaleString;
-    switch (locale) {
-        case 'en':
+export function getBestPossibleUserLocale(
+    savedLocaleString?: string,
+): Language {
+    switch (savedLocaleString) {
+        case "en":
             return Language.en;
             return Language.en;
-        case 'fr':
+        case "fr":
             return Language.fr;
             return Language.fr;
-        case 'zh':
+        case "zh":
             return Language.zh;
             return Language.zh;
-        case 'nl':
+        case "nl":
             return Language.nl;
             return Language.nl;
-        case 'es':
+        case "es":
             return Language.es;
             return Language.es;
     }
     }
 
 
     const userLocales = getUserLocales();
     const userLocales = getUserLocales();
     for (const lc of userLocales) {
     for (const lc of userLocales) {
-        if (lc.startsWith('en')) {
+        if (lc.startsWith("en")) {
             return Language.en;
             return Language.en;
-        } else if (lc.startsWith('fr')) {
+        } else if (lc.startsWith("fr")) {
             return Language.fr;
             return Language.fr;
-        } else if (lc.startsWith('zh')) {
+        } else if (lc.startsWith("zh")) {
             return Language.zh;
             return Language.zh;
-        } else if (lc.startsWith('nl')) {
+        } else if (lc.startsWith("nl")) {
             return Language.nl;
             return Language.nl;
-        } else if (lc.startsWith('es')) {
+        } else if (lc.startsWith("es")) {
             return Language.es;
             return Language.es;
         }
         }
     }
     }

+ 15 - 0
packages/utils/type-guards.ts

@@ -0,0 +1,15 @@
+/**
+ * A variant of Array.includes that allows us to use it as a type guard.
+ *
+ * It allows us to narrow the type of an arbitrary T to U if it is one of U[].
+ *
+ * TypeScript currently doesn't allow us to use the standard Array.includes as a
+ * type guard for checking if an arbitrary string is one of the known set of
+ * values. This issue and this workaround is mentioned here:
+ * - https://github.com/microsoft/TypeScript/issues/48247
+ * - https://github.com/microsoft/TypeScript/issues/26255#issuecomment-502899689
+ */
+export function includes<T, U extends T>(us: readonly U[], t: T): t is U {
+    // @ts-expect-error @typescript-eslint/no-unsafe-argument
+    return us.includes(t);
+}