1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
12 #include <cppunit/TestFixture.h>
13 #include <cppunit/TestAssert.h>
14 #include <cppunit/extensions/HelperMacros.h>
15 #include <cppunit/plugin/TestPlugIn.h>
17 #include <i18nlangtag/mslangid.hxx>
18 #include <i18nlangtag/languagetag.hxx>
20 #include <rtl/ustring.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <osl/file.hxx>
24 #include <com/sun/star/lang/Locale.hpp>
26 using namespace com::sun::star
;
28 // To test the replacement code add '&& 0' and also in
29 // source/languagetag/languagetag.cxx
30 #if defined(ENABLE_LIBLANGTAG)
31 #define USE_LIBLANGTAG 1
33 #define USE_LIBLANGTAG 0
38 class TestLanguageTag
: public CppUnit::TestFixture
42 virtual ~TestLanguageTag() {}
45 void testAllIsoLangEntries();
47 CPPUNIT_TEST_SUITE(TestLanguageTag
);
48 CPPUNIT_TEST(testAllTags
);
49 CPPUNIT_TEST(testAllIsoLangEntries
);
50 CPPUNIT_TEST_SUITE_END();
53 void TestLanguageTag::testAllTags()
56 OUString
s_de_Latn_DE( "de-Latn-DE" );
57 LanguageTag
de_DE( s_de_Latn_DE
, true );
58 OUString aBcp47
= de_DE
.getBcp47();
59 lang::Locale aLocale
= de_DE
.getLocale();
60 LanguageType nLanguageType
= de_DE
.getLanguageType();
62 CPPUNIT_ASSERT_MESSAGE("Default script should be stripped after canonicalize.", aBcp47
== "de-DE" );
63 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
64 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
65 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
66 CPPUNIT_ASSERT( nLanguageType
== LANGUAGE_GERMAN
);
67 CPPUNIT_ASSERT( de_DE
.getLanguage() == "de" );
68 CPPUNIT_ASSERT( de_DE
.getCountry() == "DE" );
69 CPPUNIT_ASSERT( de_DE
.getScript() == "" );
70 CPPUNIT_ASSERT( de_DE
.getLanguageAndScript() == "de" );
72 // The simple replacement code doesn't do any fancy stuff.
73 CPPUNIT_ASSERT_MESSAGE("Default script was stripped after canonicalize!?!", aBcp47
== s_de_Latn_DE
);
74 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
75 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
76 CPPUNIT_ASSERT( aLocale
.Variant
== "de-Latn-DE" );
77 CPPUNIT_ASSERT( nLanguageType
== LANGUAGE_SYSTEM
); // XXX not resolved!
78 CPPUNIT_ASSERT( de_DE
.getLanguage() == "de" );
79 CPPUNIT_ASSERT( de_DE
.getCountry() == "DE" );
80 CPPUNIT_ASSERT( de_DE
.getScript() == "Latn" );
81 CPPUNIT_ASSERT( de_DE
.getLanguageAndScript() == "de-Latn" );
86 OUString
s_klingon( "i-klingon" );
87 LanguageTag
klingon( s_klingon
, true );
88 lang::Locale aLocale
= klingon
.getLocale();
90 CPPUNIT_ASSERT( klingon
.getBcp47() == "tlh" );
91 CPPUNIT_ASSERT( aLocale
.Language
== "tlh" );
92 CPPUNIT_ASSERT( aLocale
.Country
== "" );
93 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
94 CPPUNIT_ASSERT( klingon
.getLanguageType() == LANGUAGE_SYSTEM
);
95 CPPUNIT_ASSERT( klingon
.isValidBcp47() == true );
96 CPPUNIT_ASSERT( klingon
.isIsoLocale() == true );
97 CPPUNIT_ASSERT( klingon
.isIsoODF() == true );
99 CPPUNIT_ASSERT( klingon
.getBcp47() == s_klingon
);
100 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
101 CPPUNIT_ASSERT( aLocale
.Country
== "" );
102 CPPUNIT_ASSERT( aLocale
.Variant
== s_klingon
);
103 CPPUNIT_ASSERT( klingon
.getLanguageType() == LANGUAGE_SYSTEM
);
104 CPPUNIT_ASSERT( klingon
.isValidBcp47() == true );
105 CPPUNIT_ASSERT( klingon
.isIsoLocale() == false );
106 CPPUNIT_ASSERT( klingon
.isIsoODF() == false );
111 OUString
s_sr_RS( "sr-RS" );
112 LanguageTag
sr_RS( s_sr_RS
, true );
113 lang::Locale aLocale
= sr_RS
.getLocale();
114 CPPUNIT_ASSERT( sr_RS
.getBcp47() == s_sr_RS
);
115 CPPUNIT_ASSERT( aLocale
.Language
== "sr" );
116 CPPUNIT_ASSERT( aLocale
.Country
== "RS" );
117 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
118 CPPUNIT_ASSERT( sr_RS
.getLanguageType() == LANGUAGE_USER_SERBIAN_CYRILLIC_SERBIA
);
119 CPPUNIT_ASSERT( sr_RS
.isValidBcp47() == true );
120 CPPUNIT_ASSERT( sr_RS
.isIsoLocale() == true );
121 CPPUNIT_ASSERT( sr_RS
.isIsoODF() == true );
125 OUString
s_sr_Latn_RS( "sr-Latn-RS" );
126 LanguageTag
sr_RS( s_sr_Latn_RS
, true );
127 lang::Locale aLocale
= sr_RS
.getLocale();
128 CPPUNIT_ASSERT( sr_RS
.getBcp47() == s_sr_Latn_RS
);
129 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
130 CPPUNIT_ASSERT( aLocale
.Country
== "RS" );
131 CPPUNIT_ASSERT( aLocale
.Variant
== s_sr_Latn_RS
);
132 /* TODO: conversion doesn't know this yet, once it does activate test. */
134 CPPUNIT_ASSERT( sr_RS
.getLanguageType() == LANGUAGE_USER_SERBIAN_LATIN_SERBIA
);
136 CPPUNIT_ASSERT( sr_RS
.getLanguageType() == LANGUAGE_SYSTEM
);
138 CPPUNIT_ASSERT( sr_RS
.isValidBcp47() == true );
139 CPPUNIT_ASSERT( sr_RS
.isIsoLocale() == false );
140 CPPUNIT_ASSERT( sr_RS
.isIsoODF() == true );
141 CPPUNIT_ASSERT( sr_RS
.getLanguage() == "sr" );
142 CPPUNIT_ASSERT( sr_RS
.getCountry() == "RS" );
143 CPPUNIT_ASSERT( sr_RS
.getScript() == "Latn" );
144 CPPUNIT_ASSERT( sr_RS
.getLanguageAndScript() == "sr-Latn" );
148 OUString
s_de_DE( "de-DE" );
149 LanguageTag
de_DE( s_de_DE
, true );
150 lang::Locale aLocale
= de_DE
.getLocale();
151 CPPUNIT_ASSERT( de_DE
.getBcp47() == s_de_DE
);
152 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
153 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
154 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
155 CPPUNIT_ASSERT( de_DE
.getLanguageType() == LANGUAGE_GERMAN
);
156 CPPUNIT_ASSERT( de_DE
.isValidBcp47() == true );
157 CPPUNIT_ASSERT( de_DE
.isIsoLocale() == true );
158 CPPUNIT_ASSERT( de_DE
.isIsoODF() == true );
159 CPPUNIT_ASSERT( de_DE
.getLanguage() == "de" );
160 CPPUNIT_ASSERT( de_DE
.getCountry() == "DE" );
161 CPPUNIT_ASSERT( de_DE
.getScript() == "" );
162 CPPUNIT_ASSERT( de_DE
.getLanguageAndScript() == "de" );
166 OUString
s_de_DE( "de-DE" );
167 LanguageTag
de_DE( lang::Locale( "de", "DE", "" ) );
168 lang::Locale aLocale
= de_DE
.getLocale();
169 CPPUNIT_ASSERT( de_DE
.getBcp47() == s_de_DE
);
170 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
171 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
172 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
173 CPPUNIT_ASSERT( de_DE
.getLanguageType() == LANGUAGE_GERMAN
);
177 OUString
s_de_DE( "de-DE" );
178 LanguageTag
de_DE( LANGUAGE_GERMAN
);
179 lang::Locale aLocale
= de_DE
.getLocale();
180 CPPUNIT_ASSERT( de_DE
.getBcp47() == s_de_DE
);
181 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
182 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
183 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
184 CPPUNIT_ASSERT( de_DE
.getLanguageType() == LANGUAGE_GERMAN
);
187 // 'qtz' is a local use known pseudolocale for key ID resource
189 OUString
s_qtz( "qtz" );
190 LanguageTag
qtz( s_qtz
);
191 lang::Locale aLocale
= qtz
.getLocale();
192 CPPUNIT_ASSERT( qtz
.getBcp47() == s_qtz
);
193 CPPUNIT_ASSERT( aLocale
.Language
== "qtz" );
194 CPPUNIT_ASSERT( aLocale
.Country
== "" );
195 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
196 CPPUNIT_ASSERT( qtz
.getLanguageType() == LANGUAGE_USER_KEYID
);
199 // 'qty' is a local use unknown locale
201 OUString
s_qty( "qty" );
202 LanguageTag
qty( s_qty
);
203 lang::Locale aLocale
= qty
.getLocale();
204 CPPUNIT_ASSERT( qty
.getBcp47() == s_qty
);
205 CPPUNIT_ASSERT( aLocale
.Language
== "qty" );
206 CPPUNIT_ASSERT( aLocale
.Country
== "" );
207 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
208 CPPUNIT_ASSERT( qty
.getLanguageType() == LANGUAGE_SYSTEM
);
211 // 'x-comment' is a privateuse known "locale"
213 OUString
s_xcomment( "x-comment" );
214 LanguageTag
xcomment( s_xcomment
);
215 lang::Locale aLocale
= xcomment
.getLocale();
216 CPPUNIT_ASSERT( xcomment
.getBcp47() == s_xcomment
);
217 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
218 CPPUNIT_ASSERT( aLocale
.Country
== "" );
219 CPPUNIT_ASSERT( aLocale
.Variant
== "x-comment" );
220 CPPUNIT_ASSERT( xcomment
.getLanguageType() == LANGUAGE_USER_PRIV_COMMENT
);
223 // 'x-foobar' is a privateuse unknown "locale"
225 OUString
s_xfoobar( "x-foobar" );
226 LanguageTag
xfoobar( s_xfoobar
);
227 lang::Locale aLocale
= xfoobar
.getLocale();
228 CPPUNIT_ASSERT( xfoobar
.getBcp47() == s_xfoobar
);
229 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
230 CPPUNIT_ASSERT( aLocale
.Country
== "" );
231 CPPUNIT_ASSERT( aLocale
.Variant
== "x-foobar" );
232 CPPUNIT_ASSERT( xfoobar
.getLanguageType() == LANGUAGE_SYSTEM
);
235 // '*' the dreaded jolly joker is a "privateuse" known "locale"
237 OUString
s_joker( "*" );
238 LanguageTag
joker( s_joker
);
239 lang::Locale aLocale
= joker
.getLocale();
240 CPPUNIT_ASSERT( joker
.getBcp47() == s_joker
);
241 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
242 CPPUNIT_ASSERT( aLocale
.Country
== "" );
243 CPPUNIT_ASSERT( aLocale
.Variant
== "*" );
244 CPPUNIT_ASSERT( joker
.getLanguageType() == LANGUAGE_USER_PRIV_JOKER
);
246 joker
.reset( LANGUAGE_USER_PRIV_JOKER
);
247 aLocale
= joker
.getLocale();
248 CPPUNIT_ASSERT( joker
.getBcp47() == s_joker
);
249 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
250 CPPUNIT_ASSERT( aLocale
.Country
== "" );
251 CPPUNIT_ASSERT( aLocale
.Variant
== "*" );
252 CPPUNIT_ASSERT( joker
.getLanguageType() == LANGUAGE_USER_PRIV_JOKER
);
255 // test reset() methods
257 LanguageTag
aTag( LANGUAGE_DONTKNOW
);
258 lang::Locale aLocale
;
260 aTag
.reset( LANGUAGE_GERMAN
);
261 aLocale
= aTag
.getLocale();
262 CPPUNIT_ASSERT( aTag
.getBcp47() == "de-DE" );
263 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
264 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
265 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
266 CPPUNIT_ASSERT( aTag
.getLanguageType() == LANGUAGE_GERMAN
);
268 aTag
.reset( "en-US" );
269 aLocale
= aTag
.getLocale();
270 CPPUNIT_ASSERT( aTag
.getBcp47() == "en-US" );
271 CPPUNIT_ASSERT( aLocale
.Language
== "en" );
272 CPPUNIT_ASSERT( aLocale
.Country
== "US" );
273 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
274 CPPUNIT_ASSERT( aTag
.getLanguageType() == LANGUAGE_ENGLISH_US
);
276 aTag
.reset( lang::Locale( "de", "DE", "" ) );
277 aLocale
= aTag
.getLocale();
278 CPPUNIT_ASSERT( aTag
.getBcp47() == "de-DE" );
279 CPPUNIT_ASSERT( aLocale
.Language
== "de" );
280 CPPUNIT_ASSERT( aLocale
.Country
== "DE" );
281 CPPUNIT_ASSERT( aLocale
.Variant
== "" );
282 CPPUNIT_ASSERT( aTag
.getLanguageType() == LANGUAGE_GERMAN
);
286 OUString
s_uab( "unreg-and-bad" );
287 LanguageTag
uab( s_uab
, true );
288 lang::Locale aLocale
= uab
.getLocale();
289 CPPUNIT_ASSERT( uab
.getBcp47() == s_uab
);
290 CPPUNIT_ASSERT( aLocale
.Language
== "qlt" );
291 CPPUNIT_ASSERT( aLocale
.Country
== "" );
292 CPPUNIT_ASSERT( aLocale
.Variant
== s_uab
);
293 CPPUNIT_ASSERT( uab
.getLanguageType() == LANGUAGE_SYSTEM
);
294 CPPUNIT_ASSERT( uab
.isValidBcp47() == false );
295 CPPUNIT_ASSERT( uab
.isIsoLocale() == false );
296 CPPUNIT_ASSERT( uab
.isIsoODF() == false );
300 void TestLanguageTag::testAllIsoLangEntries()
302 const MsLangId::IsoLangEntry
* pLangEntry
;
303 sal_Int32 nIndex
= 0;
304 while (((pLangEntry
= MsLangId::getIsoLangEntry( nIndex
++ )) != NULL
) && (pLangEntry
->mnLang
!= LANGUAGE_DONTKNOW
))
306 LanguageTag
aTagString( pLangEntry
->getTagString(), true);
307 LanguageTag
aTagID( pLangEntry
->mnLang
);
308 if (pLangEntry
->getTagString() != aTagString
.getBcp47())
310 OString
aMessage( OUStringToOString( pLangEntry
->getTagString(), RTL_TEXTENCODING_ASCII_US
));
311 aMessage
+= " -> " + OUStringToOString( aTagString
.getBcp47(), RTL_TEXTENCODING_ASCII_US
);
312 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), pLangEntry
->getTagString() == aTagString
.getBcp47());
314 if (pLangEntry
->getTagString() != aTagID
.getBcp47())
316 // There are multiple mappings, ID must be equal after conversions.
317 LanguageTag
aTagBack( aTagID
.getBcp47(), true);
318 if (aTagString
.getLanguageType() != aTagBack
.getLanguageType())
320 OString
aMessage( OUStringToOString( pLangEntry
->getTagString(), RTL_TEXTENCODING_ASCII_US
));
321 aMessage
+= " " + OString::number( aTagString
.getLanguageType(), 16) +
322 " -> " + OString::number( aTagBack
.getLanguageType(), 16);
323 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), aTagString
.getLanguageType() == aTagBack
.getLanguageType());
327 // This does not hold, there are cases like 'ar'
328 // LANGUAGE_ARABIC_PRIMARY_ONLY that when mapped back results in
329 // 'ar-SA' as default locale.
330 if (pLangEntry
->mnLang
!= aTagString
.getLanguageType())
332 // There are multiple mappings, string must be equal after conversions.
333 LanguageTag
aTagBack( aTagString
.getLanguageType());
334 if (aTagID
.getBcp47() != aTagBack
.getBcp47())
336 OString
aMessage( OUStringToOString( pLangEntry
->getTagString(), RTL_TEXTENCODING_ASCII_US
));
337 aMessage
+= " " + OUStringToOString( aTagID
.getBcp47(), RTL_TEXTENCODING_ASCII_US
) +
338 " -> " + OUStringToOString( aTagBack
.getBcp47(), RTL_TEXTENCODING_ASCII_US
);
339 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), aTagID
.getBcp47() == aTagBack
.getBcp47());
347 CPPUNIT_TEST_SUITE_REGISTRATION( TestLanguageTag
);
351 CPPUNIT_PLUGIN_IMPLEMENT();
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */