Coverage for app/venv/lib/python3.14/site-packages/weblate/trans/specialchars.py: 30%

75 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 07:15 +0000

1# Copyright © Michal Čihař <michal@weblate.org> 

2# 

3# SPDX-License-Identifier: GPL-3.0-or-later 

4 

5"""Helper code to get user special characters specific for given language.""" 

6 

7import unicodedata 

8 

9from django.conf import settings 

10from django.utils.translation import gettext, gettext_lazy 

11 

12# Names of hardcoded characters 

13CHAR_NAMES = { 

14 "\t": gettext_lazy("Insert tab character"), 

15 "\n": gettext_lazy("Insert new line"), 

16 "…": gettext_lazy("Insert horizontal ellipsis"), 

17 "\u00ad": gettext_lazy("Insert a soft hyphen"), 

18 "\u00a0": gettext_lazy("Insert a non-breaking space"), 

19} 

20DISPLAY_CHARS = {"\t": "↹", "\n": "↵", "\u00ad": "﹙-﹚"} 

21 

22 

23HYPHEN_LANGS = { 

24 "af", 

25 "am", 

26 "ar", 

27 "ast", 

28 "az", 

29 "bg", 

30 "bs", 

31 "ca", 

32 "cs", 

33 "cy", 

34 "da", 

35 "de", 

36 "dsb", 

37 "dz", 

38 "ee", 

39 "el", 

40 "en", 

41 "eo", 

42 "es", 

43 "fa", 

44 "fi", 

45 "fr", 

46 "fy", 

47 "gd", 

48 "gl", 

49 "gu", 

50 "he", 

51 "hr", 

52 "hsb", 

53 "id", 

54 "is", 

55 "ja", 

56 "ka", 

57 "kk", 

58 "kn", 

59 "ko", 

60 "ksh", 

61 "ky", 

62 "lb", 

63 "lkt", 

64 "lt", 

65 "lv", 

66 "mk", 

67 "mn", 

68 "mr", 

69 "nl", 

70 "os", 

71 "pa", 

72 "pl", 

73 "pt", 

74 "ro", 

75 "ru", 

76 "sk", 

77 "sr", 

78 "sv", 

79 "ta", 

80 "th", 

81 "to", 

82 "tr", 

83 "uz", 

84 "vi", 

85 "vo", 

86 "yi", 

87 "zh", 

88} 

89 

90EN_DASH_LANGS = { 

91 "af", 

92 "am", 

93 "ar", 

94 "ast", 

95 "az", 

96 "bg", 

97 "bs", 

98 "ca", 

99 "cs", 

100 "cy", 

101 "da", 

102 "de", 

103 "dsb", 

104 "dz", 

105 "ee", 

106 "el", 

107 "en", 

108 "eo", 

109 "es", 

110 "fi", 

111 "fr", 

112 "fy", 

113 "gd", 

114 "gl", 

115 "gu", 

116 "he", 

117 "hr", 

118 "hsb", 

119 "hu", 

120 "id", 

121 "is", 

122 "ka", 

123 "kk", 

124 "kn", 

125 "ksh", 

126 "ky", 

127 "lb", 

128 "lkt", 

129 "lt", 

130 "lv", 

131 "mk", 

132 "mn", 

133 "mr", 

134 "nb", 

135 "nl", 

136 "os", 

137 "pa", 

138 "pl", 

139 "pt", 

140 "ro", 

141 "ru", 

142 "sk", 

143 "sr", 

144 "sv", 

145 "ta", 

146 "th", 

147 "to", 

148 "tr", 

149 "uk", 

150 "uz", 

151 "vi", 

152 "vo", 

153 "yi", 

154 "zh", 

155} 

156 

157EM_DASH_LANGS = { 

158 "af", 

159 "ar", 

160 "ast", 

161 "az", 

162 "bg", 

163 "bs", 

164 "ca", 

165 "cy", 

166 "de", 

167 "dsb", 

168 "dz", 

169 "ee", 

170 "el", 

171 "en", 

172 "eo", 

173 "es", 

174 "fr", 

175 "fy", 

176 "gd", 

177 "gl", 

178 "gu", 

179 "he", 

180 "hr", 

181 "hsb", 

182 "id", 

183 "is", 

184 "it", 

185 "ja", 

186 "ka", 

187 "kk", 

188 "kn", 

189 "ko", 

190 "ksh", 

191 "ky", 

192 "lb", 

193 "lkt", 

194 "lt", 

195 "lv", 

196 "mk", 

197 "mn", 

198 "mr", 

199 "nl", 

200 "os", 

201 "pa", 

202 "pl", 

203 "pt", 

204 "ro", 

205 "ru", 

206 "sv", 

207 "ta", 

208 "th", 

209 "to", 

210 "tr", 

211 "uz", 

212 "vi", 

213 "vo", 

214 "yi", 

215 "zh", 

216} 

217 

218EXTRA_CHARS = { 

219 "brx": ("।", "॥"), 

220 "he": ("־", "״", "׳"), 

221} 

222 

223# Additional characters for RTL languages 

224RTL_CHARS = (8204, 8205, 8206, 8207, 8234, 8235, 8236, 8237, 8238) 

225 

226 

227def get_quote(code, data, name): 

228 """Return special char for quote.""" 

229 if code in data: 

230 return name, data[code], data[code] 

231 return name, data["ALL"], data["ALL"] 

232 

233 

234def get_display_char(char): 

235 name = short = char 

236 if unicodedata.category(char)[0] in {"C", "Z"}: 236 ↛ 248line 236 didn't jump to line 248 because the condition on line 236 was always true

237 # Various control and space characters 

238 try: 

239 name = unicodedata.name(char) 

240 short = "".join( 

241 x[0] for x in name.replace("-TO-", " ").replace("-", " ").split() 

242 ) 

243 except ValueError: 

244 # Char now known to unicode data 

245 # This mostly happens for control characters < 0x20 

246 name = short = char.encode("unicode_escape").decode("ascii") 

247 # Use display short name if available 

248 short = DISPLAY_CHARS.get(char, short) 

249 return name, short 

250 

251 

252def format_char(char): 

253 """Return verbose description of a character.""" 

254 name, short = get_display_char(char) 

255 if char in CHAR_NAMES: 255 ↛ 256line 255 didn't jump to line 256 because the condition on line 255 was never true

256 return CHAR_NAMES[char], short, char 

257 

258 return gettext("Insert character {0}").format(name), short, char 

259 

260 

261def get_special_chars(language, additional="", source=""): 

262 """Return list of special characters.""" 

263 for char in settings.SPECIAL_CHARS: 

264 yield format_char(char) 

265 code = language.code.replace("_", "-").split("-")[0] 

266 

267 if code in EXTRA_CHARS: 

268 for char in EXTRA_CHARS[code]: 

269 yield format_char(char) 

270 

271 yield get_quote(code, MAIN_OPEN, gettext("Main opening quote")) 

272 yield get_quote(code, MAIN_CLOSE, gettext("Main closing quote")) 

273 yield get_quote(code, ALT_OPEN, gettext("Alternative opening quote")) 

274 yield get_quote(code, ALT_CLOSE, gettext("Alternative closing quote")) 

275 

276 if code in HYPHEN_LANGS: 

277 yield format_char("\u00ad") 

278 yield gettext("Hyphen"), "‐", "‐" 

279 

280 if code in EN_DASH_LANGS: 

281 yield gettext("En dash"), "–", "–" 

282 

283 if code in EM_DASH_LANGS: 

284 yield gettext("Em dash"), "—", "—" 

285 

286 for char in additional: 

287 name, short = get_display_char(char) 

288 yield gettext("User configured character: {}").format(name), short, char 

289 

290 rtl = language.direction == "rtl" 

291 for char in set(source): 

292 try: 

293 name = unicodedata.name(char) 

294 except ValueError: 

295 continue 

296 if "ARROW" in name: 

297 if rtl and "LEFT" in name: 

298 try: 

299 char = unicodedata.lookup(name.replace("LEFT", "RIGHT")) 

300 except KeyError: 

301 continue 

302 yield format_char(char) 

303 elif rtl and "RIGHT" in name: 

304 try: 

305 char = unicodedata.lookup(name.replace("RIGHT", "LEFT")) 

306 except KeyError: 

307 continue 

308 yield format_char(char) 

309 else: 

310 yield format_char(char) 

311 

312 

313RTL_CHARS_DATA = [format_char(chr(c)) for c in RTL_CHARS] 

314 

315# Quotes data, generated using scripts/generate-specialchars.py 

316ALT_OPEN = { 

317 "ALL": "‘", 

318 "af": "‘", 

319 "agq": "‚", 

320 "ak": "‘", 

321 "am": "‹", 

322 "ar": "‘", 

323 "as": "‘", 

324 "asa": "‘", 

325 "ast": "“", 

326 "az": "‹", 

327 "bas": "„", 

328 "be": "‹", 

329 "bem": "‘", 

330 "bez": "‘", 

331 "bg": "‚", 

332 "bm": "“", 

333 "bn": "‘", 

334 "bo": "‘", 

335 "br": "‹", 

336 "brx": "‘", 

337 "bs": "‘", 

338 "ca": "“", 

339 "cgg": "‘", 

340 "chr": "‘", 

341 "cs": "‚", 

342 "cy": "‘", 

343 "da": "›", 

344 "de": "‚", 

345 "dsb": "‚", 

346 "dua": "‘", 

347 "dyo": "“", 

348 "ee": "‘", 

349 "el": "“", 

350 "en": "‘", 

351 "eo": "‘", 

352 "es": "“", 

353 "et": "‚", 

354 "eu": "‹", 

355 "ewo": "“", 

356 "fa": "‹", 

357 "ff": "‚", 

358 "fi": "’", 

359 "fil": "‘", 

360 "fo": "‘", 

361 "fr": "‹", 

362 "fur": "“", 

363 "ga": "‘", 

364 "gl": "‘", 

365 "gsw": "‹", 

366 "gu": "‘", 

367 "gv": "‘", 

368 "ha": "‘", 

369 "haw": "‘", 

370 "he": "‚", 

371 "hi": "‘", 

372 "hr": "‚", 

373 "hsb": "‚", 

374 "hu": "»", 

375 "hy": "‘", 

376 "ia": "“", 

377 "id": "‘", 

378 "ig": "‘", 

379 "ii": "‘", 

380 "is": "‚", 

381 "it": "“", 

382 "ja": "『", 

383 "jgo": "‹", 

384 "jmc": "‘", 

385 "ka": "‚", 

386 "kab": "“", 

387 "kam": "‘", 

388 "kde": "‘", 

389 "kea": "‘", 

390 "ki": "‘", 

391 "kk": "‘", 

392 "kkj": "‹", 

393 "kl": "‘", 

394 "km": "‘", 

395 "kn": "‘", 

396 "ko": "‘", 

397 "kok": "‘", 

398 "ksb": "‘", 

399 "ksh": "‚", 

400 "kw": "‘", 

401 "ky": "„", 

402 "lag": "’", 

403 "lb": "‚", 

404 "lg": "‘", 

405 "ln": "‘", 

406 "lt": "‚", 

407 "lu": "‘", 

408 "luo": "‘", 

409 "luy": "‚", 

410 "lv": "„", 

411 "mas": "‘", 

412 "mfe": "‘", 

413 "mg": "“", 

414 "mk": "‚", 

415 "ml": "‘", 

416 "mr": "‘", 

417 "ms": "‘", 

418 "mt": "‘", 

419 "mua": "“", 

420 "my": "‘", 

421 "naq": "‘", 

422 "nb_NO": "‘", 

423 "nd": "‘", 

424 "ne": "‘", 

425 "nl": "‘", 

426 "nmg": "«", 

427 "nn": "‘", 

428 "nnh": "“", 

429 "nr": "“", 

430 "nso": "“", 

431 "nyn": "‘", 

432 "om": "‘", 

433 "or": "‘", 

434 "os": "„", 

435 "pa": "‘", 

436 "pl": "«", 

437 "ps": "‘", 

438 "pt": "‘", 

439 "rm": "‹", 

440 "rn": "’", 

441 "ro": "«", 

442 "rof": "‘", 

443 "ru": "„", 

444 "rw": "‘", 

445 "rwk": "‘", 

446 "saq": "‘", 

447 "se": "’", 

448 "seh": "‘", 

449 "ses": "‘", 

450 "sg": "“", 

451 "shi": "„", 

452 "si": "‘", 

453 "sk": "‚", 

454 "sl": "‚", 

455 "sn": "’", 

456 "so": "‘", 

457 "sq": "‚", 

458 "sr": "‚", 

459 "sr_Cyrl": "‘", 

460 "sr_Latn": "‚", 

461 "ss": "“", 

462 "sv": "’", 

463 "sw": "‘", 

464 "ta": "‘", 

465 "te": "‘", 

466 "teo": "‘", 

467 "th": "‘", 

468 "ti": "‘", 

469 "tn": "“", 

470 "to": "‘", 

471 "tr": "‘", 

472 "ts": "“", 

473 "tzm": "‘", 

474 "ug": "›", 

475 "uk": "„", 

476 "ur": "‘", 

477 "uz": "‘", 

478 "uz_Latn": "‘", 

479 "vai": "‘", 

480 "ve": "“", 

481 "vi": "‘", 

482 "vo": "‘", 

483 "vun": "‘", 

484 "wae": "‹", 

485 "xog": "‘", 

486 "yav": "«", 

487 "yi": "'", 

488 "yo": "‘", 

489 "zgh": "„", 

490 "zh": "『", 

491 "zh_Hans": "‘", 

492 "zh_Hant": "『", 

493 "zu": "‘", 

494} 

495ALT_CLOSE = { 

496 "ALL": "’", 

497 "af": "’", 

498 "ak": "’", 

499 "am": "›", 

500 "ar": "’", 

501 "as": "’", 

502 "asa": "’", 

503 "ast": "”", 

504 "az": "›", 

505 "bas": "“", 

506 "be": "›", 

507 "bem": "’", 

508 "bez": "’", 

509 "bg": "‘", 

510 "bm": "”", 

511 "bn": "’", 

512 "bo": "’", 

513 "br": "›", 

514 "brx": "’", 

515 "bs": "’", 

516 "ca": "”", 

517 "cgg": "’", 

518 "chr": "’", 

519 "cs": "‘", 

520 "cy": "’", 

521 "da": "‹", 

522 "de": "‘", 

523 "dsb": "‘", 

524 "dua": "’", 

525 "dyo": "”", 

526 "ee": "’", 

527 "el": "”", 

528 "en": "’", 

529 "eo": "’", 

530 "es": "”", 

531 "et": "‘", 

532 "eu": "›", 

533 "ewo": "”", 

534 "fa": "›", 

535 "ff": "’", 

536 "fi": "’", 

537 "fil": "’", 

538 "fo": "’", 

539 "fr": "›", 

540 "fur": "”", 

541 "ga": "’", 

542 "gl": "’", 

543 "gsw": "›", 

544 "gu": "’", 

545 "gv": "’", 

546 "ha": "’", 

547 "haw": "’", 

548 "he": "’", 

549 "hi": "’", 

550 "hr": "‘", 

551 "hsb": "‘", 

552 "hu": "«", 

553 "hy": "’", 

554 "ia": "”", 

555 "id": "’", 

556 "ig": "’", 

557 "ii": "’", 

558 "is": "‘", 

559 "it": "”", 

560 "ja": "』", 

561 "jgo": "›", 

562 "jmc": "’", 

563 "ka": "‘", 

564 "kab": "”", 

565 "kam": "’", 

566 "kde": "’", 

567 "kea": "’", 

568 "ki": "’", 

569 "kk": "’", 

570 "kkj": "›", 

571 "kl": "’", 

572 "km": "’", 

573 "kn": "’", 

574 "ko": "’", 

575 "kok": "’", 

576 "ksb": "’", 

577 "ksh": "‘", 

578 "kw": "’", 

579 "ky": "“", 

580 "lag": "’", 

581 "lb": "‘", 

582 "lg": "’", 

583 "ln": "’", 

584 "lt": "‘", 

585 "lu": "’", 

586 "luo": "’", 

587 "luy": "‘", 

588 "lv": "“", 

589 "mas": "’", 

590 "mfe": "’", 

591 "mg": "”", 

592 "mk": "‘", 

593 "ml": "’", 

594 "mr": "’", 

595 "ms": "’", 

596 "mt": "’", 

597 "mua": "”", 

598 "my": "’", 

599 "naq": "’", 

600 "nb_NO": "’", 

601 "nd": "’", 

602 "ne": "’", 

603 "nl": "’", 

604 "nmg": "»", 

605 "nn": "’", 

606 "nnh": "”", 

607 "nr": "”", 

608 "nso": "”", 

609 "nyn": "’", 

610 "om": "’", 

611 "or": "’", 

612 "os": "“", 

613 "pa": "’", 

614 "pl": "»", 

615 "ps": "’", 

616 "pt": "’", 

617 "rm": "›", 

618 "rn": "’", 

619 "ro": "»", 

620 "rof": "’", 

621 "ru": "“", 

622 "rw": "’", 

623 "rwk": "’", 

624 "saq": "’", 

625 "seh": "’", 

626 "ses": "’", 

627 "sg": "”", 

628 "shi": "”", 

629 "si": "’", 

630 "sk": "‘", 

631 "sl": "‘", 

632 "sn": "’", 

633 "so": "’", 

634 "sq": "‘", 

635 "sr": "‘", 

636 "sr_Cyrl": "’", 

637 "sr_Latn": "‘", 

638 "ss": "”", 

639 "sv": "’", 

640 "sw": "’", 

641 "ta": "’", 

642 "te": "’", 

643 "teo": "’", 

644 "th": "’", 

645 "ti": "’", 

646 "tn": "”", 

647 "to": "’", 

648 "tr": "’", 

649 "ts": "”", 

650 "tzm": "’", 

651 "ug": "‹", 

652 "uk": "“", 

653 "ur": "’", 

654 "uz": "’", 

655 "uz_Latn": "’", 

656 "vai": "’", 

657 "ve": "”", 

658 "vi": "’", 

659 "vo": "’", 

660 "vun": "’", 

661 "wae": "›", 

662 "xog": "’", 

663 "yav": "»", 

664 "yi": "'", 

665 "yo": "’", 

666 "zgh": "”", 

667 "zh": "』", 

668 "zh_Hans": "’", 

669 "zh_Hant": "』", 

670 "zu": "’", 

671} 

672MAIN_OPEN = { 

673 "ALL": "“", 

674 "af": "“", 

675 "agq": "„", 

676 "ak": "“", 

677 "am": "«", 

678 "ar": "“", 

679 "as": "“", 

680 "asa": "“", 

681 "ast": "«", 

682 "az": "«", 

683 "bas": "«", 

684 "be": "«", 

685 "bem": "“", 

686 "bez": "“", 

687 "bg": "„", 

688 "bm": "«", 

689 "bn": "“", 

690 "bo": "“", 

691 "br": "«", 

692 "brx": "“", 

693 "bs": "“", 

694 "ca": "«", 

695 "cgg": "“", 

696 "chr": "“", 

697 "cs": "„", 

698 "cy": "“", 

699 "da": "»", 

700 "de": "„", 

701 "dsb": "„", 

702 "dua": "«", 

703 "dyo": "«", 

704 "ee": "“", 

705 "el": "«", 

706 "en": "“", 

707 "eo": "“", 

708 "es": "«", 

709 "et": "„", 

710 "eu": "«", 

711 "ewo": "«", 

712 "fa": "«", 

713 "ff": "„", 

714 "fi": "”", 

715 "fil": "“", 

716 "fo": "“", 

717 "fr": "«", 

718 "fur": "‘", 

719 "ga": "“", 

720 "gl": "“", 

721 "gsw": "«", 

722 "gu": "“", 

723 "gv": "“", 

724 "ha": "“", 

725 "haw": "“", 

726 "he": "„", 

727 "hi": "“", 

728 "hr": "„", 

729 "hsb": "„", 

730 "hu": "„", 

731 "hy": "“", 

732 "ia": "‘", 

733 "id": "“", 

734 "ig": "“", 

735 "ii": "“", 

736 "is": "„", 

737 "it": "«", 

738 "ja": "「", 

739 "jgo": "«", 

740 "jmc": "“", 

741 "ka": "„", 

742 "kab": "«", 

743 "kam": "“", 

744 "kde": "“", 

745 "kea": "“", 

746 "ki": "“", 

747 "kk": "“", 

748 "kkj": "«", 

749 "kl": "“", 

750 "km": "“", 

751 "kn": "“", 

752 "ko": "“", 

753 "kok": "“", 

754 "ksb": "“", 

755 "ksf": "«", 

756 "ksh": "„", 

757 "kw": "“", 

758 "ky": "«", 

759 "lag": "”", 

760 "lb": "„", 

761 "lg": "“", 

762 "ln": "“", 

763 "lt": "„", 

764 "lu": "“", 

765 "luo": "“", 

766 "luy": "„", 

767 "lv": "«", 

768 "mas": "“", 

769 "mfe": "“", 

770 "mg": "«", 

771 "mk": "„", 

772 "ml": "“", 

773 "mr": "“", 

774 "ms": "“", 

775 "mt": "“", 

776 "mua": "«", 

777 "my": "“", 

778 "naq": "“", 

779 "nb": "«", 

780 "nb_NO": "«", 

781 "nd": "“", 

782 "ne": "“", 

783 "nl": "“", 

784 "nmg": "„", 

785 "nn": "«", 

786 "nnh": "«", 

787 "nr": "‘", 

788 "nso": "‘", 

789 "nyn": "“", 

790 "om": "“", 

791 "or": "“", 

792 "os": "«", 

793 "pa": "“", 

794 "pl": "„", 

795 "ps": "“", 

796 "pt": "“", 

797 "rm": "«", 

798 "rn": "”", 

799 "ro": "„", 

800 "rof": "“", 

801 "ru": "«", 

802 "rw": "«", 

803 "rwk": "“", 

804 "saq": "“", 

805 "se": "”", 

806 "seh": "“", 

807 "ses": "“", 

808 "sg": "«", 

809 "shi": "«", 

810 "si": "“", 

811 "sk": "„", 

812 "sl": "„", 

813 "sn": "”", 

814 "so": "“", 

815 "sq": "„", 

816 "sr": "„", 

817 "sr_Cyrl": "“", 

818 "sr_Latn": "„", 

819 "ss": "‘", 

820 "sv": "”", 

821 "sw": "“", 

822 "ta": "“", 

823 "te": "“", 

824 "teo": "“", 

825 "th": "“", 

826 "ti": "“", 

827 "tn": "‘", 

828 "to": "“", 

829 "tr": "“", 

830 "ts": "‘", 

831 "tzm": "“", 

832 "ug": "»", 

833 "uk": "«", 

834 "ur": "“", 

835 "uz": "“", 

836 "uz_Latn": "“", 

837 "vai": "“", 

838 "ve": "‘", 

839 "vi": "“", 

840 "vo": "“", 

841 "vun": "“", 

842 "wae": "«", 

843 "xog": "“", 

844 "yav": "«", 

845 "yi": '"', 

846 "yo": "“", 

847 "zgh": "«", 

848 "zh": "「", 

849 "zh_Hans": "“", 

850 "zh_Hant": "「", 

851 "zu": "“", 

852} 

853MAIN_CLOSE = { 

854 "ALL": "”", 

855 "af": "”", 

856 "ak": "”", 

857 "am": "»", 

858 "ar": "”", 

859 "as": "”", 

860 "asa": "”", 

861 "ast": "»", 

862 "az": "»", 

863 "bas": "»", 

864 "be": "»", 

865 "bem": "”", 

866 "bez": "”", 

867 "bg": "“", 

868 "bm": "»", 

869 "bn": "”", 

870 "bo": "”", 

871 "br": "»", 

872 "brx": "”", 

873 "bs": "”", 

874 "ca": "»", 

875 "cgg": "”", 

876 "chr": "”", 

877 "cs": "“", 

878 "cy": "”", 

879 "da": "«", 

880 "de": "“", 

881 "dsb": "“", 

882 "dua": "»", 

883 "dyo": "»", 

884 "ee": "”", 

885 "el": "»", 

886 "en": "”", 

887 "eo": "”", 

888 "es": "»", 

889 "et": "“", 

890 "eu": "»", 

891 "ewo": "»", 

892 "fa": "»", 

893 "ff": "”", 

894 "fi": "”", 

895 "fil": "”", 

896 "fo": "”", 

897 "fr": "»", 

898 "fur": "’", 

899 "ga": "”", 

900 "gl": "”", 

901 "gsw": "»", 

902 "gu": "”", 

903 "gv": "”", 

904 "ha": "”", 

905 "haw": "”", 

906 "he": "”", 

907 "hi": "”", 

908 "hr": "“", 

909 "hsb": "“", 

910 "hu": "”", 

911 "hy": "”", 

912 "ia": "’", 

913 "id": "”", 

914 "ig": "”", 

915 "ii": "”", 

916 "is": "“", 

917 "it": "»", 

918 "ja": "」", 

919 "jgo": "»", 

920 "jmc": "”", 

921 "ka": "“", 

922 "kab": "»", 

923 "kam": "”", 

924 "kde": "”", 

925 "kea": "”", 

926 "ki": "”", 

927 "kk": "”", 

928 "kkj": "»", 

929 "kl": "”", 

930 "km": "”", 

931 "kn": "”", 

932 "ko": "”", 

933 "kok": "”", 

934 "ksb": "”", 

935 "ksf": "»", 

936 "ksh": "“", 

937 "kw": "”", 

938 "ky": "»", 

939 "lag": "”", 

940 "lb": "“", 

941 "lg": "”", 

942 "ln": "”", 

943 "lt": "“", 

944 "lu": "”", 

945 "luo": "”", 

946 "luy": "“", 

947 "lv": "»", 

948 "mas": "”", 

949 "mfe": "”", 

950 "mg": "»", 

951 "mk": "“", 

952 "ml": "”", 

953 "mr": "”", 

954 "ms": "”", 

955 "mt": "”", 

956 "mua": "»", 

957 "my": "”", 

958 "naq": "”", 

959 "nb": "»", 

960 "nb_NO": "»", 

961 "nd": "”", 

962 "ne": "”", 

963 "nl": "”", 

964 "nn": "»", 

965 "nnh": "»", 

966 "nr": "’", 

967 "nso": "’", 

968 "nyn": "”", 

969 "om": "”", 

970 "or": "”", 

971 "os": "»", 

972 "pa": "”", 

973 "pl": "”", 

974 "ps": "”", 

975 "pt": "”", 

976 "rm": "»", 

977 "rn": "”", 

978 "ro": "”", 

979 "rof": "”", 

980 "ru": "»", 

981 "rw": "»", 

982 "rwk": "”", 

983 "saq": "”", 

984 "seh": "”", 

985 "ses": "”", 

986 "sg": "»", 

987 "shi": "»", 

988 "si": "”", 

989 "sk": "“", 

990 "sl": "“", 

991 "sn": "”", 

992 "so": "”", 

993 "sq": "“", 

994 "sr": "“", 

995 "sr_Cyrl": "”", 

996 "sr_Latn": "“", 

997 "ss": "’", 

998 "sv": "”", 

999 "sw": "”", 

1000 "ta": "”", 

1001 "te": "”", 

1002 "teo": "”", 

1003 "th": "”", 

1004 "ti": "”", 

1005 "tn": "’", 

1006 "to": "”", 

1007 "tr": "”", 

1008 "ts": "’", 

1009 "tzm": "”", 

1010 "ug": "«", 

1011 "uk": "»", 

1012 "ur": "”", 

1013 "uz": "”", 

1014 "uz_Latn": "”", 

1015 "vai": "”", 

1016 "ve": "’", 

1017 "vi": "”", 

1018 "vo": "”", 

1019 "vun": "”", 

1020 "wae": "»", 

1021 "xog": "”", 

1022 "yav": "»", 

1023 "yi": '"', 

1024 "yo": "”", 

1025 "zgh": "»", 

1026 "zh": "」", 

1027 "zh_Hans": "”", 

1028 "zh_Hant": "」", 

1029 "zu": "”", 

1030}