summaryrefslogtreecommitdiffhomepage
path: root/gui/src/shared/gettext.ts
blob: cf7e91830ae0a5473c29ad572453a2ffd295c2de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import log from 'electron-log';
import fs from 'fs';
import { po } from 'gettext-parser';
import Gettext from 'node-gettext';
import path from 'path';

const SOURCE_LANGUAGE = 'en';
const LOCALES_DIR = path.resolve(__dirname, '../../locales');

export function loadTranslations(currentLocale: string, catalogue: Gettext) {
  // First look for exact match of the current locale
  const preferredLocales = [];

  if (currentLocale !== SOURCE_LANGUAGE) {
    preferredLocales.push(currentLocale);
  }

  // In case of region bound locale like en-US, fallback to en.
  const language = Gettext.getLanguageCode(currentLocale);
  if (currentLocale !== language) {
    preferredLocales.push(language);
  }

  const domain = catalogue.domain;
  for (const locale of preferredLocales) {
    if (parseTranslation(locale, domain, catalogue)) {
      log.info(`Loaded translations ${locale}/${domain}`);
      catalogue.setLocale(locale);
      return;
    }
  }

  // Reset the locale to source language if we couldn't load the catalogue for the requested locale
  // Add empty translations to suppress some of the warnings produces by node-gettext
  catalogue.addTranslations(SOURCE_LANGUAGE, domain, {});
  catalogue.setLocale(SOURCE_LANGUAGE);
}

function parseTranslation(locale: string, domain: string, catalogue: Gettext): boolean {
  const filename = path.join(LOCALES_DIR, locale, `${domain}.po`);
  let contents: string;

  try {
    contents = fs.readFileSync(filename, { encoding: 'utf8' });
  } catch (error) {
    if (error.code !== 'ENOENT') {
      log.error(`Cannot read the gettext file "${filename}": ${error.message}`);
    }
    return false;
  }

  let translations: object;
  try {
    translations = po.parse(contents);
  } catch (error) {
    log.error(`Cannot parse the gettext file "${filename}": ${error.message}`);
    return false;
  }

  catalogue.addTranslations(locale, domain, translations);

  return true;
}

function setErrorHandler(catalogue: Gettext) {
  catalogue.on('error', (error) => {
    log.warn(`Gettext error: ${error}`);
  });
}

const gettextOptions = { sourceLocale: SOURCE_LANGUAGE };

export const messages = new Gettext(gettextOptions);
messages.setTextDomain('messages');
setErrorHandler(messages);

export const relayLocations = new Gettext(gettextOptions);
relayLocations.setTextDomain('relay-locations');
setErrorHandler(relayLocations);