Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/locale.hxx>
21 :
22 : #include <rtl/ustrbuf.hxx>
23 :
24 :
25 : namespace comphelper{
26 :
27 : //-----------------------------------------------
28 : const sal_Unicode Locale::SEPERATOR_LC = (sal_Unicode)'-';
29 : const sal_Unicode Locale::SEPERATOR_CV = (sal_Unicode)'_';
30 : const sal_Unicode Locale::SEPERATOR_CV_LINUX = (sal_Unicode)'.';
31 :
32 : //-----------------------------------------------
33 2774 : const Locale Locale::X_DEFAULT()
34 : {
35 2774 : return Locale(::rtl::OUString("x"), ::rtl::OUString("default"));
36 : }
37 :
38 : //-----------------------------------------------
39 5548 : const Locale Locale::EN_US()
40 : {
41 5548 : return Locale(::rtl::OUString("en"), ::rtl::OUString("US"));
42 : }
43 :
44 : //-----------------------------------------------
45 1479 : const Locale Locale::X_NOTRANSLATE()
46 : {
47 1479 : return Locale(::rtl::OUString("x"), ::rtl::OUString("notranslate"));
48 : }
49 :
50 : //-----------------------------------------------
51 6868 : Locale::Locale(const ::rtl::OUString& sISO)
52 6868 : throw(Locale::MalFormedLocaleException)
53 : {
54 6868 : fromISO(sISO);
55 6868 : }
56 :
57 : //-----------------------------------------------
58 9801 : Locale::Locale(const ::rtl::OUString& sLanguage,
59 : const ::rtl::OUString& sCountry ,
60 9801 : const ::rtl::OUString& sVariant )
61 : {
62 : // Use set methods to check values too!
63 9801 : setLanguage(sLanguage);
64 9801 : setCountry (sCountry );
65 9801 : setVariant (sVariant );
66 9801 : }
67 :
68 : //-----------------------------------------------
69 0 : Locale::Locale()
70 : {
71 : // Initialize instance ... otherwhise user will
72 : // may be get exceptions if he e.g. copy this instance ...
73 0 : (*this) = X_NOTRANSLATE();
74 0 : }
75 :
76 : //-----------------------------------------------
77 0 : Locale::Locale(const Locale& aCopy)
78 : {
79 0 : (*this) = aCopy; // recycle assign operator
80 0 : }
81 :
82 : //-----------------------------------------------
83 0 : ::rtl::OUString Locale::getLanguage() const
84 : {
85 0 : return m_sLanguage;
86 : }
87 :
88 : //-----------------------------------------------
89 0 : ::rtl::OUString Locale::getCountry() const
90 : {
91 0 : return m_sCountry;
92 : }
93 :
94 : //-----------------------------------------------
95 0 : ::rtl::OUString Locale::getVariant() const
96 : {
97 0 : return m_sVariant;
98 : }
99 :
100 : //-----------------------------------------------
101 16669 : void Locale::setLanguage(const ::rtl::OUString& sLanguage)
102 : {
103 16669 : m_sLanguage = sLanguage;
104 16669 : }
105 :
106 : //-----------------------------------------------
107 15253 : void Locale::setCountry(const ::rtl::OUString& sCountry)
108 : {
109 15253 : m_sCountry = sCountry;
110 15253 : }
111 :
112 : //-----------------------------------------------
113 9801 : void Locale::setVariant(const ::rtl::OUString& sVariant)
114 : {
115 9801 : m_sVariant = sVariant;
116 9801 : }
117 :
118 : //-----------------------------------------------
119 : /* Attention: Use own interface methods to set the
120 : different parts of this locale. Because the
121 : check the incoming value and throw an exception
122 : automaticly ...
123 : */
124 6868 : void Locale::fromISO(const ::rtl::OUString& sISO)
125 : throw(Locale::MalFormedLocaleException)
126 : {
127 6868 : m_sLanguage = ::rtl::OUString();
128 6868 : m_sCountry = ::rtl::OUString();
129 6868 : m_sVariant = ::rtl::OUString();
130 :
131 6868 : ::rtl::OUString sParser(sISO);
132 6868 : sParser = sParser.trim();
133 :
134 6868 : sal_Int32 nStart = 0;
135 6868 : sal_Int32 nEnd = 0;
136 :
137 : // extract language part
138 6868 : nEnd = sParser.indexOf(SEPERATOR_LC, nStart);
139 6868 : if (nEnd<0)
140 : {
141 1416 : setLanguage(sParser);
142 : return;
143 : }
144 5452 : setLanguage(sParser.copy(nStart, nEnd-nStart));
145 5452 : nStart = nEnd+1;
146 :
147 : // extract country
148 5452 : nEnd = sParser.indexOf(SEPERATOR_CV, nStart);
149 5452 : if (nEnd<0)
150 5452 : nEnd = sParser.indexOf(SEPERATOR_CV_LINUX, nStart);
151 5452 : if (nEnd<0)
152 : {
153 5452 : setCountry(sParser.copy(nStart, sParser.getLength()-nStart));
154 : return;
155 : }
156 0 : nStart = nEnd+1;
157 :
158 : // extract variant
159 0 : setVariant(sParser.copy(nStart, sParser.getLength()-nStart));
160 : }
161 :
162 : //-----------------------------------------------
163 0 : ::rtl::OUString Locale::toISO() const
164 : {
165 0 : ::rtl::OUStringBuffer sISO(64);
166 :
167 0 : sISO.append(m_sLanguage);
168 0 : if (!m_sCountry.isEmpty())
169 : {
170 0 : sISO.append(SEPERATOR_LC);
171 0 : sISO.append(m_sCountry);
172 :
173 0 : if (!m_sVariant.isEmpty())
174 : {
175 0 : sISO.append(SEPERATOR_CV);
176 0 : sISO.append(m_sVariant);
177 : }
178 : }
179 :
180 0 : return sISO.makeStringAndClear();
181 : }
182 :
183 : //-----------------------------------------------
184 10071 : sal_Bool Locale::equals(const Locale& aComparable) const
185 : {
186 : return (
187 10071 : m_sLanguage.equals(aComparable.m_sLanguage) &&
188 1691 : m_sCountry.equals (aComparable.m_sCountry ) &&
189 1691 : m_sVariant.equals (aComparable.m_sVariant )
190 13453 : );
191 : }
192 :
193 : //-----------------------------------------------
194 5548 : sal_Bool Locale::similar(const Locale& aComparable) const
195 : {
196 5548 : return (m_sLanguage.equals(aComparable.m_sLanguage));
197 : }
198 :
199 : //-----------------------------------------------
200 3782 : ::std::vector< ::rtl::OUString >::const_iterator Locale::getFallback(const ::std::vector< ::rtl::OUString >& lISOList ,
201 : const ::rtl::OUString& sReferenceISO)
202 : throw(Locale::MalFormedLocaleException)
203 : {
204 3782 : Locale aReference(sReferenceISO);
205 :
206 : // Note: The same language or "en"/"en-US" should be preferred as fallback.
207 : // On the other side some localized variables doesnt use localzation in real.
208 : // May be the use a "fix" value only ... marked as X-DEFAULT or X-NOTRANSLATE.
209 : // At least it can be discussed, if any language is a valid fallback ...
210 : // But in case some office functionality depends on that (that means real functionality instead
211 : // of pure UI descriptions) we should do anything, so it can work.
212 :
213 3782 : ::std::vector< ::rtl::OUString >::const_iterator pSimilar = lISOList.end();
214 3782 : ::std::vector< ::rtl::OUString >::const_iterator pEN_US = lISOList.end();
215 3782 : ::std::vector< ::rtl::OUString >::const_iterator pEN = lISOList.end();
216 3782 : ::std::vector< ::rtl::OUString >::const_iterator pXDefault = lISOList.end();
217 3782 : ::std::vector< ::rtl::OUString >::const_iterator pXNoTranslate = lISOList.end();
218 3782 : ::std::vector< ::rtl::OUString >::const_iterator pAny = lISOList.end();
219 :
220 3782 : ::std::vector< ::rtl::OUString >::const_iterator pIt;
221 19668 : for ( pIt = lISOList.begin();
222 13112 : pIt != lISOList.end() ;
223 : ++pIt )
224 : {
225 3086 : Locale aCheck(*pIt);
226 : // found Locale, which match with 100% => return it
227 3086 : if (aCheck.equals(aReference))
228 312 : return pIt;
229 :
230 : // found similar Locale => safe it as possible fallback
231 13870 : if (
232 8322 : (pSimilar == lISOList.end()) &&
233 2774 : (aCheck.similar(aReference))
234 : )
235 : {
236 0 : pSimilar = pIt;
237 : }
238 : else
239 : // found en-US => safe it as fallback
240 16644 : if (
241 8322 : (pEN_US == lISOList.end()) &&
242 8322 : (aCheck.equals(EN_US()) )
243 : )
244 : {
245 0 : pEN_US = pIt;
246 : }
247 : else
248 : // found en[-XX] => safe it as fallback
249 16644 : if (
250 8322 : (pEN == lISOList.end() ) &&
251 8322 : (aCheck.similar(EN_US()))
252 : )
253 : {
254 0 : pEN = pIt;
255 : }
256 : else
257 : // found an explicit default value(!) => safe it as fallback
258 16644 : if (
259 8322 : (pXDefault == lISOList.end()) &&
260 8322 : (aCheck.equals(X_DEFAULT()) )
261 : )
262 : {
263 1358 : pXDefault = pIt;
264 : }
265 : else
266 : // found an implicit default value(!) => safe it as fallback
267 8496 : if (
268 4248 : (pXNoTranslate == lISOList.end()) &&
269 4248 : (aCheck.equals(X_NOTRANSLATE()) )
270 : )
271 : {
272 0 : pXNoTranslate = pIt;
273 : }
274 : else
275 : // safe the first locale, which isn't an explicit fallback
276 : // as "last possible fallback"
277 1416 : if (pAny == lISOList.end())
278 1416 : pAny = pIt;
279 3086 : }
280 :
281 3470 : if (pSimilar != lISOList.end())
282 0 : return pSimilar;
283 :
284 3470 : if (pEN_US != lISOList.end())
285 0 : return pEN_US;
286 :
287 3470 : if (pEN != lISOList.end())
288 0 : return pEN;
289 :
290 3470 : if (pXDefault != lISOList.end())
291 1358 : return pXDefault;
292 :
293 2112 : if (pXNoTranslate != lISOList.end())
294 0 : return pXNoTranslate;
295 :
296 2112 : if (pAny != lISOList.end())
297 1416 : return pAny;
298 :
299 696 : return lISOList.end();
300 : }
301 :
302 : //-----------------------------------------------
303 21 : void Locale::operator=(const Locale& rCopy)
304 : {
305 : // Take over these values without checking ...
306 : // They was already checked if the copy was constructed
307 : // and must be valid now!
308 21 : m_sLanguage = rCopy.m_sLanguage;
309 21 : m_sCountry = rCopy.m_sCountry;
310 21 : m_sVariant = rCopy.m_sVariant;
311 21 : }
312 :
313 : //-----------------------------------------------
314 0 : sal_Bool Locale::operator==(const Locale& aComparable) const
315 : {
316 0 : return equals(aComparable);
317 : }
318 :
319 : //-----------------------------------------------
320 21 : sal_Bool Locale::operator!=(const Locale& aComparable) const
321 : {
322 21 : return !equals(aComparable);
323 : }
324 :
325 : } // namespace comphelper
326 :
327 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|