Added Braille-i18n
This commit is contained in:
parent
15d697b272
commit
68f94ada73
25
extensions/fablabchemnitz/braille-l18n/braille-l18n.inx
Normal file
25
extensions/fablabchemnitz/braille-l18n/braille-l18n.inx
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Convert To Localized Braille</name>
|
||||
<id>fablabchemnitz.de.braille-l18n</id>
|
||||
<param name="locale" gui-text="Alphabet:" type="optiongroup" appearance="combo">
|
||||
<option value="en">English (ASCII)</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="gl">Galician</option>
|
||||
<option value="eu">Basque</option>
|
||||
<option value="ca">Catalan/Valencian</option>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Text" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">braille-l18n.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
504
extensions/fablabchemnitz/braille-l18n/braille-l18n.py
Normal file
504
extensions/fablabchemnitz/braille-l18n/braille-l18n.py
Normal file
@ -0,0 +1,504 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import inkex
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
# UTILITIES
|
||||
|
||||
# Common standards
|
||||
|
||||
UPPERCASE_PREFIXES = {
|
||||
chr(15): 0x2828, # uppercase prefix: https://codepoints.net/U+000F
|
||||
}
|
||||
|
||||
|
||||
LOUIS_BRAILLE_NUMBERS_PREFIX = 0x283c # Louis Braille's numbers prefix
|
||||
LOUIS_BRAILLE_NUMBERS = { # Louis Braille's original numbers codification
|
||||
"0": 0x281a,
|
||||
"1": 0x2801,
|
||||
"2": 0x2803,
|
||||
"3": 0x2809,
|
||||
"4": 0x2819,
|
||||
"5": 0x2811,
|
||||
"6": 0x280B,
|
||||
"7": 0x281b,
|
||||
"8": 0x2813,
|
||||
"9": 0x280a,
|
||||
}
|
||||
|
||||
# ---------------------
|
||||
|
||||
# English based locales
|
||||
|
||||
EN_ASCII = " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)="
|
||||
|
||||
# Spanish based locales
|
||||
|
||||
ES_LETTERS = {
|
||||
"A": 0x2801,
|
||||
"B": 0x2803,
|
||||
"C": 0x2809,
|
||||
"D": 0x2819,
|
||||
"E": 0x2811,
|
||||
"F": 0x280B,
|
||||
"G": 0x281b,
|
||||
"H": 0x2813,
|
||||
"I": 0x280a,
|
||||
"J": 0x281a,
|
||||
"K": 0x2805,
|
||||
"L": 0x2807,
|
||||
"M": 0x280d,
|
||||
"N": 0x281d,
|
||||
"Ñ": 0x283b,
|
||||
"O": 0x2815,
|
||||
"P": 0x280f,
|
||||
"Q": 0x281f,
|
||||
"R": 0x2817,
|
||||
"S": 0x280e,
|
||||
"T": 0x281e,
|
||||
"U": 0x2825,
|
||||
"V": 0x2827,
|
||||
"W": 0x283a,
|
||||
"X": 0x282d,
|
||||
"Y": 0x283d,
|
||||
"Z": 0x2835,
|
||||
}
|
||||
|
||||
ES_SIGNS = {
|
||||
" ": 0x2800, # braille space
|
||||
"ª": 0x2801, # ordinal (feminine) -> same as A
|
||||
"º": 0x2815, # ordinal (masculine) -> same as O
|
||||
"&": 0x282f,
|
||||
".": 0x2804,
|
||||
",": 0x2802,
|
||||
":": 0x2812,
|
||||
";": 0x2806,
|
||||
"¿": 0x2822,
|
||||
"?": 0x2822,
|
||||
"¡": 0x2816,
|
||||
"!": 0x2816,
|
||||
'"': 0x2826,
|
||||
"(": 0x2823,
|
||||
")": 0x281c,
|
||||
# "[": 0x2837, collides with "Á" (Spanish and Catalan)
|
||||
# "]": 0x283e, collides with "Ú" (Spanish and Catalan)
|
||||
"*": 0x2814,
|
||||
|
||||
# math
|
||||
"-": 0x2824,
|
||||
"=": 0x2836,
|
||||
"×": 0x2826, # multiplication
|
||||
"÷": 0x2832, # division
|
||||
"+": 0x2816,
|
||||
"@": 0x2810,
|
||||
}
|
||||
|
||||
ES_ACCENT_MARKS = {
|
||||
"Á": 0x2837,
|
||||
"É": 0x282e,
|
||||
"Í": 0x280c,
|
||||
"Ó": 0x282c,
|
||||
"Ú": 0x283e,
|
||||
"Ü": 0x2833,
|
||||
}
|
||||
|
||||
ES_COMBINATIONS = {
|
||||
# signs
|
||||
"%": (0x2838, 0x2834),
|
||||
"‰": (0x2838, 0x2834, 0x2834), # per mile
|
||||
"/": (0x2820, 0x2802),
|
||||
"\\": (0x2810, 0x2804),
|
||||
"<": (0x2810, 0x2805),
|
||||
">": (0x2828, 0x2802),
|
||||
"|": (0x2838, 0x2807),
|
||||
"{": (0x2810, 0x2807),
|
||||
"}": (0x2838, 0x2802),
|
||||
"–": (0x2824, 0x2824), # two different unicode dashes
|
||||
"—": (0x2824, 0x2824),
|
||||
"…": (0x2804, 0x2804, 0x2804),
|
||||
|
||||
# legal
|
||||
"©": (0x2823, 0x2828, 0x2809, 0x281c), # copyright
|
||||
"®": (0x2823, 0x2828, 0x2817, 0x281c), # registered
|
||||
"℗": (0x2823, 0x2828, 0x280f, 0x281c),
|
||||
"🄯": (0x2823, 0x2828, 0x2807, 0x281c),
|
||||
|
||||
# currencies
|
||||
"€": (0x2838, 0x2811),
|
||||
"$": (0x2838, 0x280e),
|
||||
"¢": (0x2818, 0x2809),
|
||||
"£": (0x2810, 0x282e),
|
||||
"¥": (0x2838, 0x283d),
|
||||
"¥": (0x2838, 0x283d),
|
||||
}
|
||||
|
||||
CA_ACCENT_MARKS = {
|
||||
"É": 0x283f,
|
||||
"Í": 0x280c,
|
||||
"Ó": 0x282a,
|
||||
"Ú": 0x283e,
|
||||
"À": 0x2837,
|
||||
"È": 0x282e,
|
||||
"Ò": 0x282c,
|
||||
"Ï": 0x283b,
|
||||
"Ü": 0x2833,
|
||||
"Ç": 0x282f,
|
||||
}
|
||||
|
||||
# French based locales
|
||||
|
||||
FR_LETTERS = {
|
||||
"A": 0x2801,
|
||||
"B": 0x2803,
|
||||
"C": 0x2809,
|
||||
"D": 0x2819,
|
||||
"E": 0x2811,
|
||||
"F": 0x280b,
|
||||
"G": 0x281b,
|
||||
"H": 0x2813,
|
||||
"I": 0x280a,
|
||||
"J": 0x281a,
|
||||
"K": 0x2805,
|
||||
"L": 0x2807,
|
||||
"M": 0x280d,
|
||||
"N": 0x281d,
|
||||
"O": 0x2815,
|
||||
"P": 0x280f,
|
||||
"Q": 0x281f,
|
||||
"R": 0x2817,
|
||||
"S": 0x280e,
|
||||
"T": 0x281e,
|
||||
"U": 0x2825,
|
||||
"V": 0x2827,
|
||||
"W": 0x283a,
|
||||
"X": 0x282d,
|
||||
"Y": 0x283d,
|
||||
"Z": 0x2835,
|
||||
}
|
||||
|
||||
FR_ACCENT_MARKS = {
|
||||
"É": 0x283f,
|
||||
"À": 0x2837,
|
||||
"È": 0x282e,
|
||||
"Ù": 0x283e,
|
||||
"Â": 0x2821,
|
||||
"Ê": 0x2823,
|
||||
"Î": 0x2829,
|
||||
"Ô": 0x2839,
|
||||
"Û": 0x2831,
|
||||
"Ë": 0x282b,
|
||||
"Ï": 0x283b,
|
||||
"Ü": 0x2833,
|
||||
"Ç": 0x282f,
|
||||
"Œ": 0x282a, # oe ligature
|
||||
}
|
||||
|
||||
FR_SIGNS = {
|
||||
" ": 0x2800, # braille space
|
||||
",": 0x2802,
|
||||
";": 0x2806,
|
||||
":": 0x2812,
|
||||
".": 0x2832,
|
||||
"?": 0x2822,
|
||||
"!": 0x2816,
|
||||
"«": 0x2836,
|
||||
"»": 0x2836,
|
||||
"“": 0x2836,
|
||||
"”": 0x2836,
|
||||
'"': 0x2836,
|
||||
"‘": 0x2836,
|
||||
"’": 0x2836,
|
||||
"(": 0x2826,
|
||||
")": 0x2834,
|
||||
"'": 0x2804,
|
||||
"'": 0x2804,
|
||||
"/": 0x280c,
|
||||
"@": 0x281c,
|
||||
"^": 0x2808, # elevation exponent
|
||||
"-": 0x2824,
|
||||
"+": 0x2816,
|
||||
"×": 0x2814, # multiplication
|
||||
"÷": 0x2812, # division
|
||||
"=": 0x2836,
|
||||
}
|
||||
|
||||
FR_COMBINATIONS = {
|
||||
"↔": (0x282a, 0x2812, 0x2815), # bidirectional arrow
|
||||
"←": (0x282a, 0x2812, 0x2812), # left arrow
|
||||
"→": (0x2812, 0x2812, 0x2815), # right arrow
|
||||
"…": (0x2832, 0x2832, 0x2832), # unicode ellipsis
|
||||
"–": (0x2824, 0x2824),
|
||||
"—": (0x2824, 0x2824),
|
||||
"_": (0x2810, 0x2824),
|
||||
"[": (0x2818, 0x2826),
|
||||
"]": (0x2834, 0x2803),
|
||||
"°": (0x2810, 0x2815), # degrees
|
||||
"§": (0x2810, 0x280f), # paragraph/section symbol
|
||||
"&": (0x2810, 0x283f),
|
||||
"\\": (0x2810, 0x280c),
|
||||
"#": (0x2810, 0x283c),
|
||||
"{": (0x2820, 0x2820, 0x2826),
|
||||
"}": (0x2834, 0x2804, 0x2804),
|
||||
|
||||
# math
|
||||
"µ": (0x2818, 0x280d), # micron
|
||||
"π": (0x2818, 0x280f),
|
||||
"≤": (0x2818, 0x2823),
|
||||
"≥": (0x2818, 0x281c),
|
||||
"<": (0x2810, 0x2823),
|
||||
">": (0x2810, 0x281c),
|
||||
"~": (0x2810, 0x2822),
|
||||
"*": (0x2810, 0x2814),
|
||||
"%": (0x2810, 0x282c),
|
||||
"‰": (0x2810, 0x282c, 0x282c), # per mile
|
||||
|
||||
# legal
|
||||
"©": (0x2810, 0x2809), # copyright
|
||||
"®": (0x2810, 0x2817), # registered
|
||||
"™": (0x2810, 0x281e), # trademark
|
||||
|
||||
# currencies
|
||||
"¢": (0x2818, 0x2809),
|
||||
"€": (0x2818, 0x2811),
|
||||
"£": (0x2818, 0x2807),
|
||||
"$": (0x2818, 0x280e),
|
||||
"¥": (0x2818, 0x283d),
|
||||
"¥": (0x2818, 0x283d),
|
||||
}
|
||||
|
||||
# German based locales
|
||||
|
||||
DE_ACCENT_MARKS = {
|
||||
"Ä": 0x281c,
|
||||
"Ö": 0x282a,
|
||||
"Ü": 0x2833,
|
||||
}
|
||||
|
||||
DE_SIGNS = {
|
||||
" ": 0x2800, # braille space
|
||||
",": 0x2802,
|
||||
";": 0x2806,
|
||||
":": 0x2812,
|
||||
"?": 0x2822,
|
||||
"!": 0x2816,
|
||||
"„": 0x2826,
|
||||
"“": 0x2834,
|
||||
"§": 0x282c,
|
||||
".": 0x2804,
|
||||
"–": 0x2824,
|
||||
"‚": 0x2820,
|
||||
}
|
||||
|
||||
DE_COMBINATIONS = {
|
||||
# signs
|
||||
"ß": (0x282e,), # converted to 'SS' if uppercased, so defined in combinations
|
||||
"|": (0x2810, 0x2824),
|
||||
"[": (0x2818, 0x2837),
|
||||
"]": (0x2818, 0x283e),
|
||||
"/": (0x2818, 0x280c),
|
||||
"`": (0x2820, 0x2826),
|
||||
"´": (0x2820, 0x2834),
|
||||
"/": (0x2810, 0x2802),
|
||||
"&": (0x2810, 0x2825),
|
||||
"*": (0x2820, 0x2814),
|
||||
"→": (0x2812, 0x2812, 0x2815),
|
||||
"←": (0x282a, 0x2812, 0x2812),
|
||||
"↔": (0x282a, 0x2812, 0x2812, 0x2815),
|
||||
"%": (0x283c, 0x281a, 0x2834),
|
||||
"‰": (0x283c, 0x281a, 0x2834, 0x2834),
|
||||
"°": (0x2808, 0x2834),
|
||||
"′": (0x2808, 0x2814),
|
||||
"″": (0x2808, 0x2814, 0x2814),
|
||||
"@": (0x2808, 0x281c),
|
||||
"_": (0x2808, 0x2838),
|
||||
"#": (0x2808, 0x283c),
|
||||
|
||||
# currencies
|
||||
"€": (0x2808, 0x2811),
|
||||
"$": (0x2808, 0x280e),
|
||||
"¢": (0x2808, 0x2809),
|
||||
"£": (0x2808, 0x2807),
|
||||
|
||||
# legal
|
||||
"©": (0x2836, 0x2818, 0x2809, 0x2836),
|
||||
"®": (0x2836, 0x2818, 0x2817, 0x2836),
|
||||
}
|
||||
|
||||
# END: UTILITIES
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
# LOCALE FUNCTIONS
|
||||
|
||||
def en_char_map(char):
|
||||
"""English chars mapper.
|
||||
|
||||
Source: https://en.wikipedia.org/wiki/Braille_ASCII#Braille_ASCII_values
|
||||
"""
|
||||
try:
|
||||
mapint = EN_ASCII.index(char.upper())
|
||||
except ValueError:
|
||||
return char
|
||||
return chr(mapint + 0x2800)
|
||||
|
||||
def numbers_singleuppers_combinations_factory(
|
||||
numbers_map,
|
||||
singleuppers_map,
|
||||
combinations_map, # also individual characters that are modified if uppercased
|
||||
number_prefix,
|
||||
uppercase_prefix,
|
||||
):
|
||||
"""Wrapper for various character mappers implementations."""
|
||||
def char_mapper(char):
|
||||
if char.isnumeric():
|
||||
# numeric prefix + number
|
||||
return "".join([chr(number_prefix), chr(numbers_map[char])])
|
||||
try:
|
||||
bcharint = singleuppers_map[char.upper()]
|
||||
except KeyError:
|
||||
try:
|
||||
# combinations
|
||||
return "".join([chr(num) for num in combinations_map[char]])
|
||||
except KeyError:
|
||||
return char
|
||||
else:
|
||||
# if uppercase, add uppercase prefix before letter
|
||||
if char.isupper():
|
||||
return "".join([chr(uppercase_prefix), chr(bcharint)])
|
||||
return chr(bcharint)
|
||||
return char_mapper
|
||||
|
||||
def es_char_map_loader():
|
||||
"""Spanish/Galician chars mappers.
|
||||
|
||||
Source: https://sid.usal.es/idocs/F8/FDO12069/signografiabasica.pdf
|
||||
"""
|
||||
return numbers_singleuppers_combinations_factory(
|
||||
LOUIS_BRAILLE_NUMBERS,
|
||||
{
|
||||
**ES_LETTERS,
|
||||
**ES_ACCENT_MARKS,
|
||||
**ES_SIGNS,
|
||||
**UPPERCASE_PREFIXES,
|
||||
},
|
||||
ES_COMBINATIONS,
|
||||
0x283c,
|
||||
0x2828,
|
||||
)
|
||||
|
||||
def eu_char_map_loader():
|
||||
"""Euskera chars mapper.
|
||||
|
||||
Uses the sample implementation as Spanish but without accent marks.
|
||||
|
||||
Source: https://sid.usal.es/idocs/F8/FDO12069/signografiabasica.pdf
|
||||
"""
|
||||
return numbers_singleuppers_combinations_factory(
|
||||
LOUIS_BRAILLE_NUMBERS,
|
||||
{
|
||||
**ES_LETTERS,
|
||||
**ES_SIGNS,
|
||||
**UPPERCASE_PREFIXES,
|
||||
},
|
||||
ES_COMBINATIONS,
|
||||
0x283c,
|
||||
0x2828,
|
||||
)
|
||||
|
||||
def ca_char_map_loader():
|
||||
"""Catalan/Valencian chars mappers. Uses the same implementation as
|
||||
Spanish but different accent marks.
|
||||
|
||||
Source: https://sid.usal.es/idocs/F8/FDO12069/signografiabasica.pdf
|
||||
"""
|
||||
return numbers_singleuppers_combinations_factory(
|
||||
LOUIS_BRAILLE_NUMBERS,
|
||||
{
|
||||
**ES_LETTERS,
|
||||
**CA_ACCENT_MARKS,
|
||||
**ES_SIGNS,
|
||||
**UPPERCASE_PREFIXES,
|
||||
},
|
||||
ES_COMBINATIONS,
|
||||
0x283c,
|
||||
0x2828,
|
||||
)
|
||||
|
||||
def fr_char_map_loader():
|
||||
"""French chars mapper.
|
||||
|
||||
Source: https://sid.usal.es/idocs/F8/FDO12069/signografiabasica.pdf
|
||||
"""
|
||||
return numbers_singleuppers_combinations_factory(
|
||||
LOUIS_BRAILLE_NUMBERS,
|
||||
{
|
||||
**FR_LETTERS,
|
||||
**FR_ACCENT_MARKS,
|
||||
**FR_SIGNS,
|
||||
**UPPERCASE_PREFIXES,
|
||||
},
|
||||
FR_COMBINATIONS,
|
||||
0x283c,
|
||||
0x2828,
|
||||
)
|
||||
|
||||
def de_char_map_loader():
|
||||
"""German chars mapper.
|
||||
|
||||
- For letters, uses the same dictionary as French implementation.
|
||||
|
||||
Source: http://bskdl.org/textschrift.html
|
||||
"""
|
||||
return numbers_singleuppers_combinations_factory(
|
||||
LOUIS_BRAILLE_NUMBERS,
|
||||
{
|
||||
**FR_LETTERS, # Same as French implementation
|
||||
**DE_ACCENT_MARKS,
|
||||
**DE_SIGNS,
|
||||
**UPPERCASE_PREFIXES,
|
||||
},
|
||||
DE_COMBINATIONS,
|
||||
0x283c,
|
||||
0x2828,
|
||||
)
|
||||
|
||||
# END: LOCALE FUNCTIONS
|
||||
|
||||
LOCALE_CHARMAPS = {
|
||||
"en": en_char_map, # English
|
||||
"es": es_char_map_loader, # Spanish
|
||||
"fr": fr_char_map_loader, # French
|
||||
"de": de_char_map_loader, # German
|
||||
"gl": es_char_map_loader, # Galician
|
||||
"eu": eu_char_map_loader, # Euskera
|
||||
"ca": ca_char_map_loader, # Catalan/Valencian
|
||||
}
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
# EXTENSION
|
||||
|
||||
class BrailleL18n(inkex.TextExtension):
|
||||
"""Convert to Braille giving a localized map of replacements."""
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"-l", "--locale", type=str, dest="locale", default="en",
|
||||
choices=LOCALE_CHARMAPS.keys(),
|
||||
help="Locale to use converting to Braille.",
|
||||
)
|
||||
|
||||
def process_chardata(self, text):
|
||||
"""Replaceable chardata method for processing the text."""
|
||||
chars_mapper = LOCALE_CHARMAPS[self.options.locale]
|
||||
|
||||
# `chars_mapper` could be a function loader or a characters mapper
|
||||
# itself, so check if the characters mapper is loaded and load it
|
||||
# if is created from a factory
|
||||
if "loader" in chars_mapper.__name__:
|
||||
chars_mapper = chars_mapper()
|
||||
|
||||
return ''.join(map(chars_mapper, text))
|
||||
|
||||
if __name__ == '__main__':
|
||||
BrailleL18n().run()
|
Reference in New Issue
Block a user