Localize strings

This commit is contained in:
Salvo 'LtWorf' Tomaselli 2020-10-21 13:56:59 +02:00
parent 820d10a44c
commit c64fc00987
No known key found for this signature in database
GPG Key ID: B3A7CF0C801886CF
4 changed files with 27 additions and 22 deletions

View File

@ -22,6 +22,7 @@ import os.path
import pickle import pickle
import base64 import base64
from typing import Optional, Tuple from typing import Optional, Tuple
from gettext import gettext as _
from relational.relation import Relation from relational.relation import Relation
from relational import parser from relational import parser
@ -153,7 +154,7 @@ class UserInterface:
def set_relation(self, name: str, rel: Relation) -> None: def set_relation(self, name: str, rel: Relation) -> None:
'''Sets the relation corresponding to name.''' '''Sets the relation corresponding to name.'''
if not is_valid_relation_name(name): if not is_valid_relation_name(name):
raise Exception('Invalid name for destination relation') raise Exception(_('Invalid name for destination relation'))
self.relations[name] = rel self.relations[name] = rel
def suggest_name(self, filename: str) -> Optional[str]: def suggest_name(self, filename: str) -> Optional[str]:
@ -184,7 +185,7 @@ class UserInterface:
relname is not None, adds the result to the relname is not None, adds the result to the
dictionary, with the name given in relname.''' dictionary, with the name given in relname.'''
if not is_valid_relation_name(relname): if not is_valid_relation_name(relname):
raise Exception('Invalid name for destination relation') raise Exception(_('Invalid name for destination relation'))
expr = parser.parse(query) expr = parser.parse(query)
result = expr(self.relations) result = expr(self.relations)
@ -226,10 +227,10 @@ class UserInterface:
try: try:
r = self.execute(query, relname) r = self.execute(query, relname)
except Exception as e: except Exception as e:
raise Exception('Error in query: %s\n%s' % ( raise Exception(_('Error in query: %s\n%s') % (
query, query,
str(e) str(e)
)) ))
if r is None: if r is None:
raise Exception('No query executed') raise Exception(_('No query executed'))
return r return r

View File

@ -26,6 +26,7 @@
# http://ltworf.github.io/relational/grammar.html # http://ltworf.github.io/relational/grammar.html
from typing import Optional, Union, List, Any, Dict, Literal from typing import Optional, Union, List, Any, Dict, Literal
from dataclasses import dataclass from dataclasses import dataclass
from gettext import gettext as _
from relational import rtypes from relational import rtypes
@ -55,6 +56,7 @@ __all__ = [
'parse', 'parse',
] ]
PRODUCT = '*' PRODUCT = '*'
DIFFERENCE = '-' DIFFERENCE = '-'
UNION = '' UNION = ''
@ -305,7 +307,7 @@ def parse_tokens(expression: List[Union[list, str]]) -> Node:
expression = expression[0] expression = expression[0]
if len(expression) == 0: if len(expression) == 0:
raise ParserException('Failed to parse empty expression') raise ParserException(_('Failed to parse empty expression'))
# The list contains only 1 string. Means it is the name of a relation # The list contains only 1 string. Means it is the name of a relation
if len(expression) == 1: if len(expression) == 1:
@ -330,28 +332,28 @@ def parse_tokens(expression: List[Union[list, str]]) -> Node:
if len(expression[:i]) == 0: if len(expression[:i]) == 0:
raise ParserException( raise ParserException(
f'Expected left operand for {expression[i]!r}') _(f'Expected left operand for {expression[i]!r}'))
if len(expression[i + 1:]) == 0: if len(expression[i + 1:]) == 0:
raise ParserException( raise ParserException(
f'Expected right operand for {expression[i]!r}') _(f'Expected right operand for {expression[i]!r}'))
return Binary(expression[i], parse_tokens(expression[:i]), parse_tokens(expression[i + 1:])) # type: ignore return Binary(expression[i], parse_tokens(expression[:i]), parse_tokens(expression[i + 1:])) # type: ignore
'''Searches for unary operators, parsing from right to left''' '''Searches for unary operators, parsing from right to left'''
for i in range(len(expression)): for i in range(len(expression)):
if expression[i] in u_operators: # Unary operator if expression[i] in u_operators: # Unary operator
if len(expression) <= i + 2: if len(expression) <= i + 2:
raise ParserException( raise ParserException(
f'Expected more tokens in {expression[i]!r}') _(f'Expected more tokens in {expression[i]!r}'))
elif len(expression) > i + 3: elif len(expression) > i + 3:
raise ParserException( raise ParserException(
f'Too many tokens in {expression[i]!r}') _(f'Too many tokens in {expression[i]!r}'))
return Unary( return Unary(
expression[i], # type: ignore expression[i], # type: ignore
prop=expression[1 + i].strip(), # type: ignore prop=expression[1 + i].strip(), # type: ignore
child=parse_tokens(expression[2 + i]) # type: ignore child=parse_tokens(expression[2 + i]) # type: ignore
) )
raise ParserException(f'Parse error on {expression!r}') raise ParserException(_(f'Parse error on {expression!r}'))
def _find_matching_parenthesis(expression: str, start=0, openpar='(', closepar=')') -> Optional[int]: def _find_matching_parenthesis(expression: str, start=0, openpar='(', closepar=')') -> Optional[int]:
@ -421,7 +423,7 @@ def tokenize(expression: str) -> list:
end = _find_matching_parenthesis(expression) end = _find_matching_parenthesis(expression)
if end is None: if end is None:
raise TokenizerException( raise TokenizerException(
"Missing matching ')' in '%s'" % expression) _(f'Missing matching \')\' in \'{expression}\''))
# Appends the tokenization of the content of the parenthesis # Appends the tokenization of the content of the parenthesis
items.append(tokenize(expression[1:end])) items.append(tokenize(expression[1:end]))
# Removes the entire parentesis and content from the expression # Removes the entire parentesis and content from the expression

View File

@ -24,6 +24,7 @@ from collections import deque
from typing import FrozenSet, Iterable, List, Dict, Tuple, Optional from typing import FrozenSet, Iterable, List, Dict, Tuple, Optional
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from gettext import gettext as _
from relational.rtypes import * from relational.rtypes import *
@ -88,7 +89,7 @@ class Relation:
content = [] content = []
for row in loaded['content']: for row in loaded['content']:
if len(row) != len(header): if len(row) != len(header):
raise ValueError(f'Line {row} contains an incorrect amount of values') raise ValueError(_(f'Line {row} contains an incorrect amount of values'))
t_row: Tuple[Optional[Union[int, float, str, Rdate]], ...] = load( t_row: Tuple[Optional[Union[int, float, str, Rdate]], ...] = load(
row, row,
Tuple[Optional[Union[int, float, str, Rdate]], ...], # type: ignore Tuple[Optional[Union[int, float, str, Rdate]], ...], # type: ignore
@ -136,7 +137,7 @@ class Relation:
for row in content: for row in content:
if len(row) != len(header): if len(row) != len(header):
raise ValueError(f'Line {row} contains an incorrect amount of values') raise ValueError(_(f'Line {row} contains an incorrect amount of values'))
r_content.append(row) r_content.append(row)
# Guess types # Guess types
@ -169,7 +170,7 @@ class Relation:
return other return other
elif len(self.header) == len(other.header) and self.header.sharedAttributes(other.header) == len(self.header): elif len(self.header) == len(other.header) and self.header.sharedAttributes(other.header) == len(self.header):
return other.projection(self.header) return other.projection(self.header)
raise TypeError('Relations differ: [%s] [%s]' % ( raise TypeError(_('Relations differ: [%s] [%s]') % (
','.join(self.header), ','.join(other.header) ','.join(self.header), ','.join(other.header)
)) ))
@ -180,7 +181,7 @@ class Relation:
try: try:
c_expr = compile(expr, 'selection', 'eval') c_expr = compile(expr, 'selection', 'eval')
except: except:
raise Exception(f'Failed to compile expression: {expr}') raise Exception(_(f'Failed to compile expression: {expr}'))
content = [] content = []
for i in self.content: for i in self.content:
@ -193,7 +194,7 @@ class Relation:
if eval(c_expr, attributes): if eval(c_expr, attributes):
content.append(i) content.append(i)
except Exception as e: except Exception as e:
raise Exception(f'Failed to evaluate {expr} with {i}\n{e}') raise Exception(_(f'Failed to evaluate {expr} with {i}\n{e}'))
return Relation(self.header, frozenset(content)) return Relation(self.header, frozenset(content))
def product(self, other: 'Relation') -> 'Relation': def product(self, other: 'Relation') -> 'Relation':
@ -205,7 +206,7 @@ class Relation:
raise Exception('Operand must be a relation') raise Exception('Operand must be a relation')
if self.header.sharedAttributes(other.header) != 0: if self.header.sharedAttributes(other.header) != 0:
raise Exception( raise Exception(
'Unable to perform product on relations with colliding attributes' _('Unable to perform product on relations with colliding attributes')
) )
header = Header(self.header + other.header) header = Header(self.header + other.header)
@ -231,7 +232,7 @@ class Relation:
ids = self.header.getAttributesId(attributes) ids = self.header.getAttributesId(attributes)
if len(ids) == 0: if len(ids) == 0:
raise Exception('Invalid attributes for projection') raise Exception(_('Invalid attributes for projection'))
header = Header((self.header[i] for i in ids)) header = Header((self.header[i] for i in ids))
content = frozenset(tuple((i[j] for j in ids)) for i in self.content) content = frozenset(tuple((i[j] for j in ids)) for i in self.content)
@ -472,7 +473,7 @@ class Header(tuple):
for i in self: for i in self:
if not is_valid_relation_name(i): if not is_valid_relation_name(i):
raise Exception(f'"{i}" is not a valid attribute name') raise Exception(_(f'"{i}" is not a valid attribute name'))
if len(self) != len(set(self)): if len(self) != len(set(self)):
raise Exception('Attribute names must be unique') raise Exception('Attribute names must be unique')
@ -488,12 +489,12 @@ class Header(tuple):
attrs = list(self) attrs = list(self)
for old, new in params.items(): for old, new in params.items():
if not is_valid_relation_name(new): if not is_valid_relation_name(new):
raise Exception(f'{new} is not a valid attribute name') raise Exception(_(f'{new} is not a valid attribute name'))
try: try:
id_ = attrs.index(old) id_ = attrs.index(old)
attrs[id_] = new attrs[id_] = new
except: except:
raise Exception(f'Field not found: {old}') raise Exception(_(f'Field not found: {old}'))
return Header(attrs) return Header(attrs)
def sharedAttributes(self, other: 'Header') -> int: def sharedAttributes(self, other: 'Header') -> int:

View File

@ -25,6 +25,7 @@ import keyword
import re import re
from typing import Union, Set, Any, Callable, Type, Optional from typing import Union, Set, Any, Callable, Type, Optional
from dataclasses import dataclass from dataclasses import dataclass
from gettext import gettext as _
RELATION_NAME_REGEXP = re.compile(r'^[_a-z][_a-z0-9]*$', re.IGNORECASE) RELATION_NAME_REGEXP = re.compile(r'^[_a-z][_a-z0-9]*$', re.IGNORECASE)
@ -83,7 +84,7 @@ class Rdate:
'''date: A string representing a date YYYY-MM-DD''' '''date: A string representing a date YYYY-MM-DD'''
r = _date_regexp.match(date) r = _date_regexp.match(date)
if not r: if not r:
raise ValueError(f'{date} is not a valid date') raise ValueError(_(f'{date} is not a valid date'))
year = int(r.group(1)) year = int(r.group(1))
month = int(r.group(3)) month = int(r.group(3))