Picking a strategy for translation in Laravel
Joel Clermont (00:00):
Welcome to No Compromises, a peek into the mind of two old web devs who have seen some things. This is Joel.
Aaron Saray (00:08):
And this is Aaron.
Joel Clermont (00:15):
Recent project had the need to do some translation, right? We want to present various parts of the app in different languages and today we thought we might talk about it. Because there's a couple different ways you can do that in Laravel, they have their trade-offs. So we're going to talk through how we did it on this project and hopefully share some insights there.
Aaron Saray (00:36):
Well, the first thing to know is that we're not using the Google Translate plugin on the website. There's a lot of people who do that and as a middling Spanish speaker myself, I can tell you some of the translations that Google Translate comes back in real time are, I guess accurate, but not how you would say it, you know?
Joel Clermont (00:58):
Yeah. Like, how would you say middling in Spanish? Do you know that?
Aaron Saray (01:01):
See, I knew it as soon as you... I was like, "Ah," I probably shouldn't even mention this because it's just like a test. Like, as soon as someone asked me something, I can't do it. But, yeah, that's one of the issues I ran into. So if you can afford it or if your project can afford it inline translations with a professional that can speak both languages a little bit more natively is great. There's two different ways to do those translations. There is the nested file system version, which inside of the Line folder, you can have two different ways. I guess, the easier way is the language code, like EN or ES at JSON or it's just a JSON file, then flat JSON file and the key is the translation string and the value is what that value is in that language.
Joel Clermont (01:51):
So just to show off some of my skills. Like, the key would be Hello and then the value would be Hola
Aaron Saray (01:58):
In Spanish.
Joel Clermont (02:00):
In Spanish, correct. Just to try to make it more concrete.
Aaron Saray (02:04):
Yeah, good. So that's one of the ways to do it. Then the second is, there's kind of what already exists for the validation stuff is there's a folder named after the language and then there's files named after the slug of something you're to do. So there's validation.PHP which is an array with key in value. And the key is like a slug or some sort of recognizable sort of not full sentence and the value is the whole translated string again. So it could be like a folder called ES and then greetings.PHP and on the left is a hello greeting.
Joel Clermont (02:50):
Well, right. Hello isn't the English word but it's like maybe like welcome-greeting or something. It's like a slug or a token or whatever you want to call it, it's not the English phrase.
Aaron Saray (03:03):
Yeah. When you use then translation so you can use the underscore method or there's ATTLING directive and Blade, and there's Trans, T-R-A-N-S, Helper, and Trans_Choice. There's a number of different ways to do these sort of translations and depending on if it found the slug or if found the words, it'll translate that into whatever language you've currently set the app to. So that's how it works. Then basically these two things are identical. I guess there's order of precedence, one will come stronger than the other, but-
Joel Clermont (03:44):
Oh, you mean if you use both?
Aaron Saray (03:46):
Yeah. But if you don't have any overlaps it doesn't really matter. The interesting question we ran into is how should we do our translation. Should we pick folder-based system with the PHP arrays or should we do the one JSON file? And there's a number of questions on why we thought either would be better or worse or whatnot. So the first one-
Joel Clermont (04:07):
No, I was just going to say the difference too, some of the context might be your workflow for translation too. I was talking with someone else that was also in the middle of a multilingual site and the path he chose was because not only was there going to be multiple external translators, but there was going to be a lot of churn in what was being translated. It was more of like a content-based system that was going to have a lot of stuff added to it. Whereas ours is less that and more of like a typical web application. So just kind of throwing that out there. This isn't the one true answer but it's the one we picked because of our workflow.
Aaron Saray (04:44):
Right, yeah. In general, like I said, the folder-based or the file-based PHP one is slugs with values and then JSON one is the English or whatever primary language is, and then the value on the other side is the translation. One of the things that really drives me nuts is the first thing I considered is, it happened to me on my banking website once, and of course when it's money you really freak out. But it was like I finished paying something and it was like payment.successful, that was the message. And I was like, "Ah, someone forgot to translate a string."
Joel Clermont (05:18):
Right.
Aaron Saray (05:19):
So I found that to be more disconcerting than if it would've, I guess, said it in Spanish or something. Then I'd be like, "Oh, they picked the wrong language to say something like that." So I'm kind of putting myself into place of if I was a Spanish speaker and everything was in Spanish and then all of a sudden there was one phrase in English but that's pretty common for a mistakes point of view, right?
Joel Clermont (05:45):
Mm-hmm (affirmative).
Aaron Saray (05:45):
Versus having just a slug in there. So the first thing we thought about was, "What is the fallback situation?" So when translation works it tries to find a key and if it can't find a key it just displays the key then.
Joel Clermont (06:02):
Oh, okay. So that's the scenario you had just mentioned with your bank where it showed you a slug that was never really meant for any human to see in public.
Aaron Saray (06:10):
Right. So it'd be like if you didn't have... in the validation ones if you removed the required thing with a missing field, instead of saying the name field is required it would say validation.required. What does that mean? So I guess theoretically you could probably try to shoehorn in a full sentence into the PHP sort of nested system but it's certainly not made to do that. The JSON file is the one that basically has phrases on the left and phrases on the right. So that was the first sort of thing we went and thought about. The second was kind of like you said, again, what's the workflow? And I thought it might be easier to take a full JSON file and give it to someone and say, "Can you make this into Spanish or French?" or something. Versus giving them a couple different PHP files and saying, "Open up each one of these and try to put in your translations."
Joel Clermont (07:11):
Yeah. I'm just thinking too because you said one was JSON, one is a PHP rate. I guess from a syntax perspective, if this translator is a non-programmer they're both probably equally as simple or complex. But, yeah. I wonder too, are there tools where like... I mean, is this a common format where somebody could have a UI where they just drop in a JSON file and it presents it to them and they translate it? I've seen that on open-source projects but I kind of think it wasn't just a JSON file, I think it was like a special kind of translation.
Aaron Saray (07:47):
Yeah, PO file.
Joel Clermont (07:47):
Okay, I don't remember.
Aaron Saray (07:49):
I don't recall what it stands for but there's a format to do this. I think the other thing is with having that JSON file having the phrase on the left, it gives more context to the translator. Like, seeing a message that says the name field is required is much easier to understand what their goal is to translate it into it, versus field-required.
Joel Clermont (08:13):
Right, yeah.
Aaron Saray (08:14):
I don't really know what that's supposed to mean.
Joel Clermont (08:16):
Yeah, you'd almost have to give them the full set of English files and the empty set of the target language files. And then not only do you have multiple files for the language you're translating, but then multiple files to actually read the original text. So, yeah, it does feel a little more cumbersome.
Aaron Saray (08:32):
Yeah. You'd have to have more files. Some of the drawbacks that I guess I ran into or that I'm a little concerned about is this JSON file is getting larger and larger as my app grows out. So there's something in my mind, like I think about this almost like code which maybe I shouldn't be. Which is that, well, now it's 1,000 lines, now it's 2,000 lines because I've translated all those different strings to my thing.
Joel Clermont (08:57):
Sure.
Aaron Saray (08:57):
Maybe that should be in folders or separate files but that's not what this is set up to do. If that's the sort of thing that bothers you, I can see how that'd be a problem. But again, I think it has a lot more benefits.
Joel Clermont (09:09):
Yeah. I think it'd have to get pretty big for it to be performance-impact unlike opening it in an editor. You have to have like several meg file and even that I think most apps can handle that. But were you thinking more like performance of the live app as it's using the translation file too or is that a separate concern?
Aaron Saray (09:28):
No, I think it was just like... No, as you've been programming for a while, you start to get these little flags that go off in your head whether or not they're accurate.
Joel Clermont (09:37):
Code smell type thing.
Aaron Saray (09:38):
Yeah. And sometimes they're not accurate, they don't necessarily apply. But I've just trained myself like, this is too large. Well, okay, but what can do about it? Nothing.
Joel Clermont (09:46):
Exactly.
Aaron Saray (09:46):
Okay, so then I guess it's not too large. Then I think the final thing I would say is... It's kind of a tangent on this subject. But one of the things I've also seen people do is try to break up their strings because they want to do bolding or if they want to do a certain type of replacement or formatting or whatnot. And you really have to think about that because where you might break up your string in English is not the same as how someone might say it in a different language.
Joel Clermont (10:16):
No.
Aaron Saray (10:16):
When you put out string, you have a full sentence that makes sense and you split it in half because you want to do something that may not be a directly translatable thing. When you're working with these translation stuff it makes more sense to just make these full sentences and use replacements. And can you imagine that if you're using the slug-based version, what would you say? Like, alert error part one and alert error part two? Like, how would you do that?
Joel Clermont (10:46):
Yeah, I've definitely faced that situation where it was split up and then you go to translate it or use the translation and it's like the words are in a different order in this language you can't... Yeah, the segmentation in English doesn't apply to Hebrew or something else.
Aaron Saray (11:01):
Yeah. I guess the summary of all this is we kind of chose to do the JSON version of this. There are maybe some small drawbacks, like it's a large file or whatnot but it makes most sense based off the workflow. And I think it's going to make most sense for most people too because you're not going to see the random slugs. It'll at least fall back to a sentence maybe in a different language but it'll be a sentence. And I think it would probably be easier if you give one file with context to a translator versus slugs and then have to say, "Well, cross reference this other file."
Joel Clermont (11:37):
Yeah, makes perfect sense.
Aaron Saray (11:44):
I remember being in third grade and we were doing a spelling bee. And I don't know why this sticks in my head, but there was this one kid. Well, his parents owned a bar and he spent a lot of time there so his clothes and all this different stuff kind of reflected his experiences. He would wear like band t-shirts and stuff as a third grader where I even knew enough, like, I don't know what that is. I'm pretty certain it means something adult at a bar. We were doing a spelling bee and it came up to his turn, I don't know why this sticks in my head, but the teacher goes spell giraffe. You know, the long-necked animal, giraffe.
Joel Clermont (12:28):
I'm familiar.
Aaron Saray (12:29):
And he goes, "Okay, D-R-A-F-T."
Joel Clermont (12:31):
What?
Aaron Saray (12:35):
It was like, what? And then I realized like, "Oh of course. Because he sees probably draft beers all the time."
Joel Clermont (12:41):
I think that's why the professional spelling bee people say, "Could you use it in a sentence," just to make sure you're not like mishearing it.
Aaron Saray (12:51):
So you're saying as third graders we weren't professional?
Joel Clermont (12:55):
No, no, that was the minor leagues. I was just thinking when you talked about the band shirts and things is there a rule in spelling bees that you can't wear a shirt that has words on it? Because could that be a form of cheating?
Aaron Saray (13:09):
Yeah. How do you spell Metallica? Oh. No, I don't think they're proper nouns, are they?
Joel Clermont (13:14):
Well, it wouldn't have to be a proper noun. It could be The World Destruction Tour and then destruction is like one of your words and like, "Oh, one second," you just like look down at your shirt.
Aaron Saray (13:23):
I love your understanding what band shirts would be. You know, things bands have like World Destruction Tours.
Joel Clermont (13:29):
I guarantee that's a shirt somewhere from a band.
Aaron Saray (13:33):
Yeah, I'm just going to have to check online real quick.
Joel Clermont (13:35):
Okay.
Aaron Saray (13:35):
You know you want to validate your user input but you maybe just don't know where to start.
Joel Clermont (13:45):
We built a worksheet. Maybe you'll find it helpful, it'll get you started validating. Go to masteringlaravel.io/worksheet.