summaryrefslogtreecommitdiff
path: root/svl
diff options
context:
space:
mode:
authorNaruhiko Ogasawara <naruoga@gmail.com>2020-05-06 20:55:49 +0900
committerEike Rathke <erack@redhat.com>2020-05-25 22:51:22 +0200
commit9efd7cd637d9d882f2fc8277b657ec117c591e80 (patch)
tree0b68c76e33f30cc94eea9d7d409ae47b11f109d8 /svl
parent20f3a7e461381eb0db3e4ff526b69f3b1185c1c9 (diff)
tdf#130193: Asian Excel-Calc number format interop
remap NatNum - DBNum in Japanese/Chinese to improve Excel interoprability from DBNum to NatNum (import) in ja/zh: - DBNum1 -> NatNum4 (modern long Kanji text) - DBNum2 -> NatNum5 (traditional long Kanji text) - DBNum3 -> NatNum3 (fullwidth Arabic digits) from NatNum to DBNum (export) in ja: - NatNum1 -> DBNum1 - NatNum2 -> DBNum2 - NatNum3 -> DBNum3 - NatNum4 -> DBNum1 - NatNum5 -> DBNum2 - NatNum6 -> DBNum3 - NatNum7 -> DBNum1 - NatNum8 -> DBNum2 - NatNum9 -> (DBNum0, as Arabic) in zh, nothing change about export. It also partially solves the issue tdf#130140 (about Japanese, not Korean) To do this, more data-drivened MapDBNumToNatNum() and MapNatNumToDBNum() in svl/source/numbers/zformat.cxx By mapping "NatNum - DBNum" to a table using map and array, it makes the specification for each language more understandable The new test cases are also included in svl/qa/unit/svl.cxx Change-Id: I34a70d970ef2e46c1b3db5db1c397ab89c056191 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94376 Tested-by: Jenkins Reviewed-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'svl')
-rw-r--r--svl/qa/unit/svl.cxx91
-rw-r--r--svl/source/numbers/zformat.cxx96
2 files changed, 111 insertions, 76 deletions
diff --git a/svl/qa/unit/svl.cxx b/svl/qa/unit/svl.cxx
index fc541861f182..80be2b2af79a 100644
--- a/svl/qa/unit/svl.cxx
+++ b/svl/qa/unit/svl.cxx
@@ -1453,6 +1453,97 @@ void Test::testUserDefinedNumberFormats()
checkPreviewString(aFormatter, sCode, M_PI, eLang, sExpected);
#endif
}
+ { // tdf#130193 tdf#130140 Native Number Formats mapping for Chinese (Traditonal), Japanese, Korean
+ // -- Traditional Chinese: DBNum1 -> NatNum4, DBNum2 -> NatNum5, DBnum3 -> NatNum3
+
+ // DBNum1 -> NatNum4: Chinese lower case text for 123456789
+ // 一億二千三百四十五萬六千七百八十九
+ sExpected = u"\u4e00\u5104\u4e8c\u5343\u4e09\u767e\u56db\u5341\u4e94\u842c\u516d\u5343"
+ u"\u4e03\u767e\u516b\u5341\u4e5d ";
+ sCode = "[NatNum4][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum1][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum2 -> NatNum5: Chinese upper case text
+ // 壹億貳仟參佰肆拾伍萬陸仟柒佰捌拾玖
+ sExpected = u"\u58f9\u5104\u8cb3\u4edf\u53c3\u4f70\u8086\u62fe\u4f0d\u842c\u9678\u4edf"
+ u"\u67d2\u4f70\u634c\u62fe\u7396 ";
+ sCode = "[NatNum5][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum2][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum3 -> NatNum3: fullwidth text
+ // 123456789
+ sExpected = u"\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19 ";
+ sCode = "[NatNum3][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum3][$-0404]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // -- Japanese: DBNum1 -> NatNum4, DBNum2 -> NatNum5, DBnum3 -> NatNum3
+
+ // DBNum1 -> NatNum4: Japanese modern long Kanji text for 123456789
+ // 一億二千三百四十五万六千七百八十九
+ sExpected = u"\u4e00\u5104\u4e8c\u5343\u4e09\u767e\u56db\u5341\u4e94\u4e07\u516d\u5343"
+ u"\u4e03\u767e\u516b\u5341\u4e5d ";
+ sCode = "[NatNum4][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum1][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum2 -> NatNum5: traditional long Kanji text
+ // 壱億弐阡参百四拾伍萬六阡七百八拾九
+ sExpected = u"\u58f1\u5104\u5f10\u9621\u53c2\u767e\u56db\u62fe\u4f0d\u842c\u516d\u9621"
+ u"\u4e03\u767e\u516b\u62fe\u4e5d ";
+ sCode = "[NatNum5][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum2][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum3 -> NatNum3: fullwidth Arabic digits
+ // 123456789
+ sExpected = u"\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19 ";
+ sCode = "[NatNum3][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum3][$-0411]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // -- Korean: DBNum1 -> NatNum1, DBNum2 -> NatNum2, DBNum3 -> NatNum4, DBNum4 -> NatNum9
+
+ // DBNum1 -> NatNum1: Korean lower case characters
+ // 一二三四五六七八九
+ sExpected = u"\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d ";
+ sCode = "[NatNum1][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum1][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum2 -> NatNum2: Korean upper case characters
+ // 壹貳參四伍六七八九
+ sExpected = u"\u58f9\u8cb3\u53c3\u56db\u4f0d\u516d\u4e03\u516b\u4e5d ";
+ sCode = "[NatNum2][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum2][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum3 -> NatNum3: fullwidth Arabic digits
+ // 123456789
+ sExpected = u"\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19 ";
+ sCode = "[NatNum3][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum3][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+
+ // DBNum4 -> NatNum9: Hangul characters
+ // 일이삼사오육칠팔구
+ sExpected = u"\uc77c\uc774\uc0bc\uc0ac\uc624\uc721\uce60\ud314\uad6c ";
+ sCode = "[NatNum9][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ sCode = "[DBNum4][$-0412]General\\ ";
+ checkPreviewString(aFormatter, sCode, 123456789, eLang, sExpected);
+ }
{ // tdf#105968 engineering format with value rounded up to next magnitude
sCode = "##0.00E+00";
sExpected = "100.00E+00";
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 8e78cf6ee613..af68a340f3d0 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -44,6 +44,7 @@
#include <svl/nfsymbol.hxx>
#include <cmath>
+#include <array>
using namespace svt;
@@ -137,6 +138,11 @@ void ImpSvNumberformatInfo::Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt
nCntExp = rNumFor.nCntExp;
}
+static const std::map<LanguageType, std::array<sal_uInt8, 4>> tblDBNumToNatNum
+ = { { primary(LANGUAGE_CHINESE), { 4, 5, 3, 0 } },
+ { primary(LANGUAGE_JAPANESE), { 4, 5, 3, 0 } },
+ { primary(LANGUAGE_KOREAN), { 1, 2, 3, 9 } } };
+
// static
sal_uInt8 SvNumberNatNum::MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, bool bDate )
{
@@ -156,43 +162,22 @@ sal_uInt8 SvNumberNatNum::MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang
}
else
{
- switch ( nDBNum )
+ if (1 <= nDBNum && nDBNum <= 4)
{
- case 1:
- if ( eLang == primary(LANGUAGE_CHINESE) )
- nNatNum = 4;
- else if ( eLang == primary(LANGUAGE_JAPANESE) )
- nNatNum = 1;
- else if ( eLang == primary(LANGUAGE_KOREAN) )
- nNatNum = 1;
- break;
- case 2:
- if ( eLang == primary(LANGUAGE_CHINESE))
- nNatNum = 5;
- else if ( eLang == primary(LANGUAGE_JAPANESE) )
- nNatNum = 4;
- else if ( eLang == primary(LANGUAGE_KOREAN) )
- nNatNum = 2;
- break;
- case 3:
- if ( eLang == primary(LANGUAGE_CHINESE) )
- nNatNum = 6;
- else if ( eLang == primary(LANGUAGE_JAPANESE) )
- nNatNum = 5;
- else if ( eLang == primary(LANGUAGE_KOREAN) )
- nNatNum = 3;
- break;
- case 4:
- if ( eLang == primary(LANGUAGE_JAPANESE) )
- nNatNum = 7;
- else if ( eLang == primary(LANGUAGE_KOREAN) )
- nNatNum = 9;
- break;
+ auto const it = tblDBNumToNatNum.find(eLang);
+ if (it != tblDBNumToNatNum.end())
+ nNatNum = it->second[nDBNum - 1];
+
}
}
return nNatNum;
}
+static const std::map<LanguageType, std::array<sal_uInt8, 9>> tblNatNumToDBNum
+ = { { primary(LANGUAGE_CHINESE), { 1, 0, 0, 1, 2, 3, 0, 0, 0 } },
+ { primary(LANGUAGE_JAPANESE), { 1, 2, 3, 1, 2, 3, 1, 2, 0 } },
+ { primary(LANGUAGE_KOREAN), { 0, 2, 3, 1, 0, 0, 0, 0, 0 } } };
+
// static
sal_uInt8 SvNumberNatNum::MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, bool bDate )
{
@@ -212,52 +197,11 @@ sal_uInt8 SvNumberNatNum::MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLan
}
else
{
- switch ( nNatNum )
+ if (1 <= nNatNum && nNatNum <= 9)
{
- case 1:
- if ( eLang == primary(LANGUAGE_JAPANESE) )
- nDBNum = 1;
- else if ( eLang == primary(LANGUAGE_KOREAN) )
- nDBNum = 1;
- break;
- case 2:
- if ( eLang == primary(LANGUAGE_KOREAN) )
- nDBNum = 2;
- break;
- case 3:
- if ( eLang == primary(LANGUAGE_KOREAN) )
- nDBNum = 3;
- break;
- case 4:
- if ( eLang == primary(LANGUAGE_CHINESE) )
- nDBNum = 1;
- else if ( eLang == primary(LANGUAGE_JAPANESE) )
- nDBNum = 2;
- break;
- case 5:
- if ( eLang == primary(LANGUAGE_CHINESE) )
- nDBNum = 2;
- else if ( eLang == primary(LANGUAGE_JAPANESE) )
- nDBNum = 3;
- break;
- case 6:
- if ( eLang == primary(LANGUAGE_CHINESE) )
- nDBNum = 3;
- break;
- case 7:
- if ( eLang == primary(LANGUAGE_JAPANESE) )
- nDBNum = 4;
- break;
- case 8:
- break;
- case 9:
- if ( eLang == primary(LANGUAGE_KOREAN) )
- nDBNum = 4;
- break;
- case 10:
- break;
- case 11:
- break;
+ auto const it = tblNatNumToDBNum.find(eLang);
+ if (it != tblNatNumToDBNum.end())
+ nDBNum = it->second[nNatNum - 1];
}
}
return nDBNum;