What does the error mean?
The grammar for the match/case statement treats the _
as a wildcard pattern. The only acceptable token that can follow is a colon. Since your code uses an open parenthesis, a SyntaxError is raised.
How to fix it
Switch from a literal pattern such as case "north": ...
to a value pattern such as case Directions.north: ...
which uses dot-operator.
The translation can then be performed upstream, outside of the case statement:
from gettext import gettext as _
class Directions:
north = _('north')
south = _('south')
east = _('east')
west = _('west')
direction = input(_('Enter a direction: '))
match direction:
case Directions.north:
adj = 1, 0
case Directions.south:
adj = -1, 0
case Directions.east:
adj = 0, 1
case Directions.west:
adj = 0, -1
case _:
raise ValueError(_('Unknown direction'))
Not only do the string literals get translated, the case statements are more readable as well.
More advanced and dynamic solution
The above solution only works if the choice of language is constant. If the language can change (perhaps in an online application serving users from difference countries), dynamic lookups are needed.
First we need a descriptor to dynamically forward value pattern attribute lookups to function calls:
class FuncCall:
"Descriptor to convert fc.name to func(name)."
def __init__(self, func):
self.func = func
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, objtype=None):
return self.func(self.name)
We use it like this:
class Directions:
north = FuncCall(_) # calls _('north') for every lookup
south = FuncCall(_)
east = FuncCall(_)
west = FuncCall(_)
def convert(direction):
match direction:
case Directions.north:
return 1, 0
case Directions.south:
return -1, 0
case Directions.east:
return 0, 1
case Directions.west:
return 0, -1
case _:
raise ValueError(_('Unknown direction'))
print('Adjustment:', adj)
Here is a sample session:
>>> set_language('es') # Spanish
>>> convert('sur')
(-1, 0)
>>> set_language('fr') # French
>>> convert('nord')
(1, 0)
Namespaces for the Value Pattern
Any namespace with dotted lookup can be used in the value pattern: SimpleNamespace, Enum, modules, classes, instances, etc.
Here a class was chosen because it is simple and will work with the descriptor needed for the more advanced solution.
Enum wasn't considered because it is much more complex and because its metaclass logic interferes with the descriptors. Also, Enum is intended for giving symbolic names to predefined constants rather than for dynamically computed values like we're using here.
types.SimpleNamespace
? – Imitate