From 9540a486ec858233d18fbae980a9bd7cec2fb235 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 2 Nov 2020 11:22:54 +0100
Subject: [PATCH] Fix About page crashing when instance language is not
 supported

Use the languages defined by CLDR on server instead, and fallback to
english if not defined

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/graphql/admin.ts              |  9 +++++++++
 js/src/views/About/AboutInstance.vue | 22 ++++++++++++++++++++--
 lib/graphql/resolvers/admin.ex       | 16 ++++++++++++++++
 lib/graphql/schema/admin.ex          |  1 +
 4 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/js/src/graphql/admin.ts b/js/src/graphql/admin.ts
index b93624ebb..f6aa1978a 100644
--- a/js/src/graphql/admin.ts
+++ b/js/src/graphql/admin.ts
@@ -128,6 +128,15 @@ export const LANGUAGES = gql`
   }
 `;
 
+export const LANGUAGES_CODES = gql`
+  query LanguagesCodes($codes: [String!]) {
+    languages(codes: $codes) {
+      code
+      name
+    }
+  }
+`;
+
 export const ADMIN_SETTINGS_FRAGMENT = gql`
   fragment adminSettingsFragment on AdminSettings {
     instanceName
diff --git a/js/src/views/About/AboutInstance.vue b/js/src/views/About/AboutInstance.vue
index fdad1e4d8..bd3139989 100644
--- a/js/src/views/About/AboutInstance.vue
+++ b/js/src/views/About/AboutInstance.vue
@@ -44,7 +44,7 @@
       <table class="table is-fullwidth">
         <tr>
           <td>{{ $t("Instance languages") }}</td>
-          <td>{{ formatList(config.languages.map((lang) => getLanguageNameForCode(lang))) }}</td>
+          <td :title="this.config.languages.join(', ')">{{ formattedLanguageList }}</td>
         </tr>
         <tr>
           <td>{{ $t("Mobilizon version") }}</td>
@@ -78,6 +78,8 @@
 <script lang="ts">
 import { Component, Vue } from "vue-property-decorator";
 import { formatList } from "@/utils/i18n";
+import { LANGUAGES_CODES } from "@/graphql/admin";
+import { ILanguage } from "@/types/admin.model";
 import { ABOUT } from "../../graphql/config";
 import { STATISTICS } from "../../graphql/statistics";
 import { IConfig } from "../../types/config.model";
@@ -88,6 +90,17 @@ import langs from "../../i18n/langs.json";
   apollo: {
     config: ABOUT,
     statistics: STATISTICS,
+    languages: {
+      query: LANGUAGES_CODES,
+      variables() {
+        return {
+          codes: this.config.languages,
+        };
+      },
+      skip() {
+        return !this.config.languages;
+      },
+    },
   },
 })
 export default class AboutInstance extends Vue {
@@ -95,7 +108,7 @@ export default class AboutInstance extends Vue {
 
   statistics!: IStatistics;
 
-  formatList = formatList;
+  languages!: ILanguage[];
 
   get isContactEmail(): boolean {
     return this.config && this.config.contact.includes("@");
@@ -105,6 +118,11 @@ export default class AboutInstance extends Vue {
     return this.config && this.config.contact.match(/^https?:\/\//g) !== null;
   }
 
+  get formattedLanguageList(): string {
+    const list = this.languages.map(({ name }) => name);
+    return formatList(list);
+  }
+
   // eslint-disable-next-line class-methods-use-this
   getLanguageNameForCode(code: string): string {
     const languageMaps = langs as Record<string, any>;
diff --git a/lib/graphql/resolvers/admin.ex b/lib/graphql/resolvers/admin.ex
index 19927d43e..55eedeaf0 100644
--- a/lib/graphql/resolvers/admin.ex
+++ b/lib/graphql/resolvers/admin.ex
@@ -157,6 +157,22 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
     end
   end
 
+  def get_list_of_languages(_parent, %{codes: codes}, _resolution) when is_list(codes) do
+    locale = Gettext.get_locale()
+    locale = if Cldr.known_locale_name?(locale), do: locale, else: "en"
+
+    case Language.known_languages(locale) do
+      data when is_map(data) ->
+        data
+        |> Enum.map(fn {code, elem} -> %{code: code, name: elem.standard} end)
+        |> Enum.filter(fn %{code: code, name: _name} -> code in codes end)
+        |> (&{:ok, &1}).()
+
+      {:error, err} ->
+        {:error, err}
+    end
+  end
+
   def get_list_of_languages(_parent, _args, _resolution) do
     locale = Gettext.get_locale()
 
diff --git a/lib/graphql/schema/admin.ex b/lib/graphql/schema/admin.ex
index 9e74611cd..4161824bf 100644
--- a/lib/graphql/schema/admin.ex
+++ b/lib/graphql/schema/admin.ex
@@ -123,6 +123,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
     end
 
     field :languages, type: list_of(:language) do
+      arg(:codes, list_of(:string))
       resolve(&Admin.get_list_of_languages/3)
     end