summaryrefslogtreecommitdiffhomepage
path: root/gui/src/shared/gettext.ts
blob: b466a44134e4c919f83f1aff5298e391e90c86be (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
80
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';
let SELECTED_LANGUAGE = SOURCE_LANGUAGE;
const LOCALES_DIR = path.resolve(__dirname, '../../locales');

// `{debug: false}` option prevents Gettext from printing the warnings to console in development
// the errors are handled separately in the "error" handler below
const catalogue = new Gettext({ debug: false });
catalogue.setTextDomain('messages');
catalogue.on('error', (error) => {
  // Filter out the "no translation was found" errors for the source language
  if (SELECTED_LANGUAGE === SOURCE_LANGUAGE && error.indexOf('No translation was found') !== -1) {
    return;
  }

  log.warn(`Gettext error: ${error}`);
});

export function loadTranslations(currentLocale: string) {
  // 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);
  }

  for (const locale of preferredLocales) {
    if (parseTranslation(locale, 'messages')) {
      log.info(`Loaded translations for ${locale}`);
      catalogue.setLocale(locale);

      SELECTED_LANGUAGE = locale;
      return;
    }
  }
}

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

  try {
    buffer = fs.readFileSync(filename);
  } 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(buffer);
  } catch (error) {
    log.error(`Cannot parse the gettext file "${filename}": ${error.message}`);
    return false;
  }

  catalogue.addTranslations(locale, domain, translations);

  return true;
}

export const gettext = (msgid: string): string => {
  return catalogue.gettext(msgid);
};
export const pgettext = (msgctx: string, msgid: string): string => {
  return catalogue.pgettext(msgctx, msgid);
};