@@ -974,12 +974,41 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
974974 const QString &commonNameI18n,
975975 const QString &abbrevI18n) const
976976{
977+ // Each element may be in an RTL language (e.g. Arab). However, we want a canonical order of left to right elements.
978+ // This requires building Unicode isolation cells.
979+ // Unicode constants from Unicode Standard Annex #9, section 2.
980+ // static const QString LRE{"\u202a"}; // Left-to-right embedding: Treat following text as embedded left-to-right
981+ // static const QString RLE{"\u202b"}; // Right-to-left embedding: Treat following text as embedded right-to-left
982+ // static const QString LRO{"\u202d"}; // Left-to-right override: Force following characters to be treated as strong left-to-right chars.
983+ // static const QString RLO{"\u202e"}; // Right-to-left override: Force following characters to be treated as strong right-to-left chars.
984+ // static const QString PDF{"\u202c"}; // Pop directional formatting: terminate scope of last LRE/RLE/LRO/RLO
985+ static const QString LRI{" \u2066 " }; // left-to-right isolate: Treat following text as isolated and left-to-right
986+ static const QString RLI{" \u2067 " }; // right-to-left isolate: Treat following text as isolated and right-to-left
987+ static const QString FSI{" \u2068 " }; // First strong isolate: Treat following text as isolated and in the direction of its first strong directional character.
988+ // ASSUMPTION: Can be used as autodetect feature? Mark all parts inside embeddings?
989+ static const QString PDI{" \u2069 " }; // Pop directional isolate: terminate scope of last LRI/RLI/FSI
990+ // static const QString LRM{"\u200e"}; // left-to-right mark: zero-width char
991+ // static const QString RLM{"\u200f"}; // right-to-left mark: right to left zero-width non-Arabic char
992+ // static const QString ALM{"\u061c"}; // right-to-left mark: right to left zero-width Arabic char
993+
994+ StelObject::CulturalName lName;
995+ // copy over filled elements from cName, but enclose each with Unicode isolation markers.
996+ if (!cName.native .isEmpty ()) lName.native = FSI+cName.native +PDI;
997+ if (!cName.pronounce .isEmpty ()) lName.pronounce = FSI+cName.pronounce +PDI;
998+ if (!cName.pronounceI18n .isEmpty ()) lName.pronounceI18n = FSI+cName.pronounceI18n +PDI;
999+ if (!cName.transliteration .isEmpty ()) lName.transliteration = FSI+cName.transliteration +PDI;
1000+ if (!cName.translated .isEmpty ()) lName.translated = FSI+cName.translated +PDI;
1001+ if (!cName.translatedI18n .isEmpty ()) lName.translatedI18n = FSI+cName.translatedI18n +PDI;
1002+ if (!cName.IPA .isEmpty ()) lName.IPA = FSI+cName.IPA +PDI;
1003+ if (!cName.byname .isEmpty ()) lName.byname = FSI+cName.byname +PDI;
1004+ if (!cName.bynameI18n .isEmpty ()) lName.bynameI18n = FSI+cName.bynameI18n +PDI;
1005+
9771006 // At least while many fields have not been filled, we should create a few fallbacks
9781007 // If native contains non-Latin glyphs, pronounce or transliteration is mandatory.
979- QString pronounceStr=(cName .pronounceI18n .isEmpty () ? cName .pronounce : cName .pronounceI18n );
980- QString nativeOrPronounce = (cName .native .isEmpty () ? cName .pronounceI18n : cName .native );
981- QString pronounceOrNative = (cName .pronounceI18n .isEmpty () ? cName .native : cName .pronounceI18n );
982- QString translitOrPronounce = (cName .transliteration .isEmpty () ? pronounceStr : cName .transliteration );
1008+ QString pronounceStr=(lName .pronounceI18n .isEmpty () ? lName .pronounce : lName .pronounceI18n );
1009+ QString nativeOrPronounce = (lName .native .isEmpty () ? lName .pronounceI18n : lName .native );
1010+ QString pronounceOrNative = (lName .pronounceI18n .isEmpty () ? lName .native : lName .pronounceI18n );
1011+ QString translitOrPronounce = (lName .transliteration .isEmpty () ? pronounceStr : lName .transliteration );
9831012
9841013 // If you call this with an actual argument abbrevI18n, you really only want a short label.
9851014 if (flagUseAbbreviatedNames && !abbrevI18n.isNull ())
@@ -990,20 +1019,20 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
9901019 switch (style)
9911020 {
9921021 case StelObject::CulturalDisplayStyle::Native: // native if available. fallback to pronounce and english entries
993- return cName .native .isEmpty () ? (cName .pronounceI18n .isEmpty () ? cName .translatedI18n : cName .pronounceI18n ) : cName .native ;
1022+ return lName .native .isEmpty () ? (lName .pronounceI18n .isEmpty () ? lName .translatedI18n : lName .pronounceI18n ) : lName .native ;
9941023 case StelObject::CulturalDisplayStyle::Pronounce: // pronounce if available. fallback to native
9951024 return pronounceOrNative;
9961025 case StelObject::CulturalDisplayStyle::Translit:
9971026 return translitOrPronounce;
9981027 case StelObject::CulturalDisplayStyle::Translated:
999- return (cName .translatedI18n .isEmpty () ? (pronounceStr.isEmpty () ? cName .native : pronounceStr) : cName .translatedI18n );
1028+ return (lName .translatedI18n .isEmpty () ? (pronounceStr.isEmpty () ? lName .native : pronounceStr) : lName .translatedI18n );
10001029 case StelObject::CulturalDisplayStyle::IPA: // really only IPA?
1001- return cName .IPA ;
1030+ return lName .IPA ;
10021031 case StelObject::CulturalDisplayStyle::NONE: // fully non-cultural!
10031032 case StelObject::CulturalDisplayStyle::Modern:
10041033 return commonNameI18n;
10051034 case StelObject::CulturalDisplayStyle::Byname:
1006- return (cName .bynameI18n .isEmpty () ? (pronounceStr.isEmpty () ? cName .native : pronounceStr) : cName .bynameI18n );
1035+ return (lName .bynameI18n .isEmpty () ? (pronounceStr.isEmpty () ? lName .native : pronounceStr) : lName .bynameI18n );
10071036 default :
10081037 break ;
10091038 }
@@ -1026,7 +1055,7 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10261055 if (styleInt & int (StelObject::CulturalDisplayStyle::Pronounce))
10271056 braced.append (pronounceStr);
10281057 if (styleInt & int (StelObject::CulturalDisplayStyle::Translit))
1029- braced.append (cName .transliteration );
1058+ braced.append (lName .transliteration );
10301059 }
10311060 else // not including native
10321061 {
@@ -1035,7 +1064,7 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10351064 {
10361065 label=pronounceOrNative;
10371066 if (styleInt & int (StelObject::CulturalDisplayStyle::Translit))
1038- braced.append (cName .transliteration );
1067+ braced.append (lName .transliteration );
10391068 }
10401069
10411070 else if (styleInt & int (StelObject::CulturalDisplayStyle::Translit))
@@ -1048,33 +1077,34 @@ QString StelSkyCultureMgr::createCulturalLabel(const StelObject::CulturalName &c
10481077 braced.removeOne (QString (" " ));
10491078 braced.removeOne (QString ());
10501079 braced.removeOne (label); // avoid repeating the main thing if it was used as fallback!
1080+
10511081 if (!braced.isEmpty ()) label.append (QString (" %1%3%2" ).arg (QChar (0x2997 ), QChar (0x2998 ), braced.join (" , " )));
10521082
10531083 // Add IPA (where possible)
1054- if ((styleInt & int (StelObject::CulturalDisplayStyle::IPA)) && (!cName .IPA .isEmpty ()) && (label != cName .IPA ))
1055- label.append (QString (" [%1]" ).arg (cName .IPA ));
1084+ if ((styleInt & int (StelObject::CulturalDisplayStyle::IPA)) && (!lName .IPA .isEmpty ()) && (label != lName .IPA ))
1085+ label.append (QString (" [%1]" ).arg (lName .IPA ));
10561086
10571087 // Add translation and optional byname in brackets
10581088
10591089 QStringList bracketed;
1060- if ((styleInt & int (StelObject::CulturalDisplayStyle::Translated)) && (!cName .translatedI18n .isEmpty ()))
1090+ if ((styleInt & int (StelObject::CulturalDisplayStyle::Translated)) && (!lName .translatedI18n .isEmpty ()))
10611091 {
10621092 if (label.isEmpty ())
1063- label=cName .translatedI18n ;
1064- else if (!label.startsWith (cName .translatedI18n , Qt::CaseInsensitive)) // seems useless to add translation into same string
1093+ label=lName .translatedI18n ;
1094+ else if (!label.startsWith (lName .translatedI18n , Qt::CaseInsensitive)) // seems useless to add translation into same string
10651095
1066- // label.append(QString(" (%1)").arg(cName .translatedI18n));
1067- bracketed.append (cName .translatedI18n );
1096+ // label.append(QString(" (%1)").arg(lName .translatedI18n));
1097+ bracketed.append (lName .translatedI18n );
10681098 }
10691099
1070- if ( (styleInt & int (StelObject::CulturalDisplayStyle::Byname)) && (!cName .bynameI18n .isEmpty ()))
1071- bracketed.append (cName .bynameI18n );
1100+ if ( (styleInt & int (StelObject::CulturalDisplayStyle::Byname)) && (!lName .bynameI18n .isEmpty ()))
1101+ bracketed.append (lName .bynameI18n );
10721102 if (!bracketed.isEmpty ())
10731103 label.append (QString (" (%1)" ).arg (bracketed.join (" , " )));
10741104
10751105
10761106 // Add an explanatory modern name in decorative angle brackets
1077- if ((styleInt & int (StelObject::CulturalDisplayStyle::Modern)) && (!commonNameI18n.isEmpty ()) && (!label.startsWith (commonNameI18n)) && (commonNameI18n!=cName .translatedI18n ))
1107+ if ((styleInt & int (StelObject::CulturalDisplayStyle::Modern)) && (!commonNameI18n.isEmpty ()) && (!label.startsWith (commonNameI18n)) && (commonNameI18n!=lName .translatedI18n ))
10781108 label.append (QString (" %1%3%2" ).arg (QChar (0x29FC ), QChar (0x29FD ), commonNameI18n));
10791109 if ((styleInt & int (StelObject::CulturalDisplayStyle::Modern)) && label.isEmpty ()) // if something went wrong?
10801110 label=commonNameI18n;
0 commit comments