summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/LangCodeExpander.h
blob: dc9e5dc48a9b062a937377c31cc1f00de1b98793 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include <map>
#include <string>
#include <vector>

class TiXmlElement;

class CLangCodeExpander
{
public:
  CLangCodeExpander();
  ~CLangCodeExpander();

  enum LANGFORMATS
  {
    ISO_639_1,
    ISO_639_2,
    ENGLISH_NAME
  };

  enum class LANG_LIST
  {
    // Standard ISO
    DEFAULT,
    // Standard ISO + Language addons
    INCLUDE_ADDONS,
    // Standard ISO + User defined
    // (User defined can override language name of existing codes)
    INCLUDE_USERDEFINED,
    // Standard ISO + Language addons + User defined
    // (User defined can override language name of existing codes)
    INCLUDE_ADDONS_USERDEFINED,
  };

  void LoadUserCodes(const TiXmlElement* pRootElement);
  void Clear();

  bool Lookup(const std::string& code, std::string& desc);
  bool Lookup(const int code, std::string& desc);

  /** \brief Determines if two english language names represent the same language.
  *   \param[in] lang1 The first language string to compare given as english language name.
  *   \param[in] lang2 The second language string to compare given as english language name.
  *   \return true if the two language strings represent the same language, false otherwise.
  *   For example "Abkhaz" and "Abkhazian" represent the same language.
  */
  bool CompareFullLanguageNames(const std::string& lang1, const std::string& lang2);

  /** \brief Determines if two languages given as ISO 639-1, ISO 639-2/T, or ISO 639-2/B codes represent the same language.
  *   \param[in] code1 The first language to compare given as ISO 639-1, ISO 639-2/T, or ISO 639-2/B code.
  *   \param[in] code2 The second language to compare given as ISO 639-1, ISO 639-2/T, or ISO 639-2/B code.
  *   \return true if the two language codes represent the same language, false otherwise.
  *   For example "ger", "deu" and "de" represent the same language.
  */
  bool CompareISO639Codes(const std::string& code1, const std::string& code2);

  /** \brief Converts a language given as 2-Char (ISO 639-1),
  *          3-Char (ISO 639-2/T or ISO 639-2/B),
  *          or full english name string to a 2-Char (ISO 639-1) code.
  *   \param[out] code The 2-Char language code of the given language lang.
  *   \param[in] lang The language that should be converted.
  *   \return true if the conversion succeeded, false otherwise.
  */
  bool ConvertToISO6391(const std::string& lang, std::string& code);

  /** \brief Converts a language given as 2-Char (ISO 639-1),
  *          3-Char (ISO 639-2/T or ISO 639-2/B),
  *          or full english name string to a 3-Char ISO 639-2/B code.
  *   \param[in] lang The language that should be converted.
  *   \return The 3-Char ISO 639-2/B code of lang if that code exists, lang otherwise.
  */
  std::string ConvertToISO6392B(const std::string& lang);

  /** \brief Converts a language given as 2-Char (ISO 639-1) to a 3-Char (ISO 639-2/T) code.
  *   \param[in] strISO6391 The language that should be converted.
  *   \param[out] strISO6392B The 3-Char (ISO 639-2/B) language code of the given language strISO6391.
  *   \param[in] checkWin32Locales Whether to also check WIN32 specific language codes.
  *   \return true if the conversion succeeded, false otherwise.
  */
  static bool ConvertISO6391ToISO6392B(const std::string& strISO6391, std::string& strISO6392B, bool checkWin32Locales = false);

  /** \brief Converts a language given as 2-Char (ISO 639-1),
  *          3-Char (ISO 639-2/T or ISO 639-2/B),
  *          or full english name string to a 3-Char ISO 639-2/T code.
  *   \param[in] strCharCode The language that should be converted.
  *   \param[out] strISO6392B The 3-Char (ISO 639-2/B) language code of the given language strISO6391.
  *   \param[in] checkWin32Locales Whether to also check WIN32 specific language codes.
  *   \return true if the conversion succeeded, false otherwise.
  */
  bool ConvertToISO6392B(const std::string& strCharCode, std::string& strISO6392B, bool checkWin32Locales = false);

  /** \brief Converts a language given as 2-Char (ISO 639-1),
  *          3-Char (ISO 639-2/T or ISO 639-2/B),
  *          or full english name string to a 3-Char ISO 639-2/T code.
  *   \param[in] strCharCode The language that should be converted.
  *   \param[out] strISO6392T The 3-Char (ISO 639-2/T) language code of the given language strISO6391.
  *   \param[in] checkWin32Locales Whether to also check WIN32 specific language codes.
  *   \return true if the conversion succeeded, false otherwise.
  */
  bool ConvertToISO6392T(const std::string& strCharCode, std::string& strISO6392T, bool checkWin32Locales = false);

  /** \brief Converts a language given as 2-Char (ISO 639-1),
  *          3-Char (ISO 639-2/T or ISO 639-2/B),
  *          or full english name string to a 3-Char ISO 639-2/T code.
  *   \param[in] lang The language that should be converted.
  *   \return The 3-Char ISO 639-2/T code of lang if that code exists, lang otherwise.
  */
  std::string ConvertToISO6392T(const std::string& lang);

  /*
   * \brief Find a language code with subtag (e.g. zh-tw, zh-Hans) in to a string.
   *        This function find a limited set of IETF BCP47 specs, so:
   *        language tag + region subtag, or, language tag + script subtag.
   *        The language code can be found also if wrapped with round brackets.
   * \param str The string where find the language code.
   * \return The language code found in the string, otherwise empty string
   */
  static std::string FindLanguageCodeWithSubtag(const std::string& str);

#ifdef TARGET_WINDOWS
  static bool ConvertISO31661Alpha2ToISO31661Alpha3(const std::string& strISO31661Alpha2, std::string& strISO31661Alpha3);
  static bool ConvertWindowsLanguageCodeToISO6392B(const std::string& strWindowsLanguageCode, std::string& strISO6392B);
#endif

  /*
   * \brief Get the list of language names.
   * \param format [OPT] The format type.
   * \param list [OPT] The type of language list to retrieve.
   * \return The languages
   */
  std::vector<std::string> GetLanguageNames(LANGFORMATS format = ISO_639_1,
                                            LANG_LIST list = LANG_LIST::DEFAULT);

protected:
  /*
   * \brief Converts a language code given as a long, see #MAKECODE(a, b, c, d)
   *        to its string representation.
   * \param[in] code The language code given as a long, see #MAKECODE(a, b, c, d).
   * \return The string representation of the given language code code.
   */
  static std::string CodeToString(long code);

  static bool LookupInISO639Tables(const std::string& code, std::string& desc);

  /*
   * \brief Looks up the language description for given language code
   *        in to the installed language addons.
   * \param[in] code The language code for which description is looked for.
   * \param[out] desc The english language name.
   * \return true if the language description was found, false otherwise.
   */
  static bool LookupInLangAddons(const std::string& code, std::string& desc);

  bool LookupInUserMap(const std::string& code, std::string& desc);

  /** \brief Looks up the ISO 639-1, ISO 639-2/T, or ISO 639-2/B, whichever it finds first,
  *          code of the given english language name.
  *   \param[in] desc The english language name for which a code is looked for.
  *   \param[out] code The ISO 639-1, ISO 639-2/T, or ISO 639-2/B code of the given language desc.
  *   \return true if the a code was found, false otherwise.
  */
  bool ReverseLookup(const std::string& desc, std::string& code);


  /** \brief Looks up the user defined code of the given code or language name.
  *   \param[in] desc The language code or name that should be converted.
  *   \param[out] userCode The user defined language code of the given language desc.
  *   \return true if desc was found, false otherwise.
  */
  bool LookupUserCode(const std::string& desc, std::string &userCode);

  typedef std::map<std::string, std::string> STRINGLOOKUPTABLE;
  STRINGLOOKUPTABLE m_mapUser;
};

extern CLangCodeExpander g_LangCodeExpander;