hwuethrich
Hi!
I’m happy to share my first Elixir library. But first some …
Background
As an Elixir company from a country with 4 official languages (
), trust me when I say: we are using Gettext a lot in our Phoenix projects.
I really love the features of Gettext, but it always bothered me that it adds a lot of noise in the code, especially when using domains/contexts, interpolations or pluralization (besides, I still can’t remember which Gettext macro to use when using domains and/or contexts
).
That’s why until now, we always added a ~t sigil to all our (phoenix) projects that simply delegates to gettext. We also had an m modifier that is using the current module name (eg. live view/component) as context.
Over the last few days, I extracted this (and more!) as a library called …
gettext_sigils
It provides a new sigil ~t (which felt oddly familiar) for using Gettext translations with less boilerplate and better readability:
# before
gettext("Hello, %{name}", name: user.name)
# after
~t"Hello, #{user.name}"
When using GettextSigils (eg. in your MyAppWeb.html_helpers/0 for Phoenix projects), you can also provide how modifiers are mapped do domains and/or contexts:
# replace this
use Gettext, backend: MyApp.Gettext
# with this
use GettextSigils,
backend: MyApp.Gettext
sigils: [
modifiers: [
m: [context: inspect(__MODULE__)],
e: [domain: "errors"]
]
]
# then use it instead of gettext
~t"This is a global message"
~t"This is scoped to the current module/view/component"m
~t"This is a scoped error message"em
If this sounds interesting, there are a few other features, all described in the README.
As this is a very new project, contributions, bug reports and feedback in general are very welcome. I’m currently working on adding pluralization (which is a bit tricky when all you have is a sigil) where I would love some feedback (PR).
Thanks! Danke! Merci! Grazie! Grazia! ![]()
Trending in News & Updates
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
ErikNaslund
Thanks a bunch for this! I’ve also always been bothered by the verbosity of having
gettext()calls all over my .heex templates, but I’ve never done anything about it.I just migrated one of my projects to using GettextSigils, and one quirky regex replace and some small amount of manual editing later I was all done and it was working like a charm
Great “quality of life” improvement, so thanks again!
P.S.
A serendipitous side effect is that my syntax highlighting scheme highlights sigil strings differently than normal binary strings, so it became a lot easier to spot “language strings” vs other strings (like CSS classes etc) in the templates as well.
josevalim
Love the idea!
hwuethrich
Thank you so much for the feedback!
I’m glad to know I wasn’t the only one bothered by the additional noise.
Here are some ideas I’d like to add until 1.x:
‖(UTF-8 double vertical bar), but it’s not typeable. I’m thinking of maybe using something like//would be better.@docforsigil_tthat includes a list of modifiers (and what they are mapped to) that is displayed by the editor when using the sigil.~tin an app (in case gettext was not used from the start).DaAnalyst
Nice. I already implemented something like this for internationalizing our project, but plain macros, e.g:
What I’ve found extremely useful (and so implemented it) was the ability to define domain at the module level and so that all the
t/1, t/2, tn/3, tn/4macros can use it without having to specify it on case by case basis, e.g:hwuethrich
Thanks for the feedback!
This is already possible by specifying the
sigils: [domain: "edit_post"]option when using the module.Using plain macros definitely has some benefits (if the macro takes more the 1 string, eg. pluralization).
BartOtten
Lovely. Had a POC that extracted all text from Heex (no sigil needed) but had issues with Gettext, HTML and variables. Maybe you could have a try as you clearly have more experience with Gettext
Except from splitting sentences on every variabele and Heex-tag, it worked miracles. Every text from the app became a Gettext translatable message
Help tool to check the tokenizer steps: GitHub - BartOtten/eex_visualizer: Visualizes the compilation steps of (h)EEx · GitHub
hwuethrich
I just released v0.2.1 of the library with the following features:
igniter install task
installiing the library now automatically replaces
use Gettextwithuse GettextSigilsin the project. this allows installing and configuring the library with:usage rules & skill
I added usage rules to teach LLMs to use
~tinstead of fixed strings for newly generated code. also comes with a skill that will:replace fixed strings with
~tin any user-facing part of the application (HEEx templates)suggest using ex_cldr when showing dates, time, numbers, etc.
at the end of a task, asks to translate the new Gettext message for all languages used in the project (optional)
this works for newly generated code and existing parts of the project!
While this might be a bit controversial (my wife is actually working as a translator
), this has been a real time-saver and localizing an existing app is now easier than ever! At least it should mark the generated translations as “fuzzy”. See skill source and LLM guide.
hwuethrich
This sounds interesting and scary at the same time!
I assume there are a lot of edge cases like translated DOM attributes, args for nested components, embedded JS?
wintermeyer
I love the idea! I run into this problem in every single Phoenix project.
Only the pluralization needs to be solved in a clean way since that is a showstopper.
hwuethrich
Thanks for the feedback! Yeah, finding a clean solution for pluralization is a bit difficult (and that’s why I haven’t merged this PR, yet)
For now, I think this is my favorite solution so far:
It uses
Nto mark it as pluralization (separator can still be used in regular translations, omitting the separator in pluralizations will raise an error)But I’m open to other ideas!