Een PHP-applicatie internationaliseren betekent niet alleen knoppen en berichten vertalen. Een applicatie die is voorbereid op meerdere talen of markten moet taal, regionale formaten, tijdzone, valuta, inhoud en bedrijfsbeleid scheiden. Als deze lagen worden vermengd, kan elke uitbreiding veranderen in een functionele vertakking die moeilijk te testen en te onderhouden is.
Wat verandert er bij werken in meerdere talen en markten

De taal bepaalt hoe een tekst wordt uitgedrukt. De regionale instelling, of landinstelling, definieert presentatieconventies zoals het decimaalteken, de volgorde van datums of de groepering van duizendtallen. Een landinstelling kan een regio bevatten, zoals es-ES of fr-CA, maar die regio mag niet in de plaats komen van de markt, de juridische entiteit, de fiscale woonplaats, het commerciële beleid of het operationele land.
Het is ook raadzaam om contexten te onderscheiden die vaak samen voorkomen, maar niet hetzelfde betekenen:
- Tijdzone: interpreteert tijden, termijnen, agenda's en operationele afsluitingen.
- Valuta: identificeert het bedrag van een transactie of prijslijst; deze wordt niet afgeleid uit de taal.
- Organisatie of juridische entiteit: kan belastingen, vergunningen, facturatie of gegevensbewaring bepalen.
- Markt: kan van invloed zijn op catalogus, logistiek, betaalmethoden of beschikbare kanalen.
- Gebruikersvoorkeuren: gekozen taal, landinstelling en tijdzone, die kunnen afwijken van de bedrijfsconfiguratie.
Iemand kan de interface in het Engels gebruiken, in een Europese tijdzone werken en een organisatie beheren die in een andere valuta factureert. Die realiteit terugbrengen tot één enkele variabele locale creëert impliciete beslissingen.
De kostbare fout: taal omzetten in een bedrijfsregel
Een slecht teken doet zich voor wanneer de code domeinbeslissingen neemt op basis van de interfacetaal: if ($locale === 'es'). Die voorwaarde kan beginnen met het tonen van een ander label en eindigen met het toepassen van belastingen, het verbergen van een betaalmethode of het wijzigen van een goedkeuring.
De juiste vraag is: “welk gegeven of beleid verklaart deze variatie?”. Als dit afhangt van een juridische entiteit, moet die entiteit worden geraadpleegd. Als het voortvloeit uit commercieel beleid, moet er een identificeerbaar en versioneerbaar beleid bestaan. Als het alleen de representatie beïnvloedt, hoort het bij de grens van invoer of uitvoer.
De taal geeft vorm aan de gebruikerservaring; zij autoriseert, berekent of definieert op zichzelf niet het gedrag van het domein.
Wat in het domein moet blijven
Het domein moet werken met stabiele concepten en canonieke waarden. Een bestelling heeft hoeveelheden, bedragen, regels, statussen en berekeningsregels nodig; zij hoeft niet te weten of een bedrag wordt weergegeven als 1,234.50 of 1.234,50. Een geschiktheidsbeleid moet expliciete attributen ontvangen, niet de presentatie van de gebruiker uitlezen.
- Domein: invarianten, statussen, berekeningen, zakelijke bevoegdheden, beleidsregels en gebeurtenissen.
- Applicatie: gebruiksscenario's, laden van context, coördinatie en selectie van beleidsregels.
- Invoeradapters: formulieren, kopteksten, API's of bestanden; validatie en normalisatie.
- Uitvoeradapters: vertaling, serialisatie en opmaak van datums, bedragen en eenheden.
Vermijd in PHP dat entiteiten en centrale services rechtstreeks sessies, HTTP-kopteksten, omgevingsvariabelen of de globale landinstelling van het proces raadplegen. Deze afhankelijkheden zorgen ervoor dat hetzelfde gebruiksscenario zich anders gedraagt afhankelijk van het kanaal of het uitvoeringsmoment.
Een expliciete en begrensde context ontwerpen
Een ExecutionContext kan een organisatie-ID, actor, landinstelling voor presentatie en voorkeurstijdzone bevatten. Elk veld moet duidelijke semantiek hebben. De valuta van een bewerking moet echter deel uitmaken van het bedrag of van het toegepaste prijsbeleid, niet van een wijzigbare globale voorkeur.
Los de context op aan de rand van elk kanaal. Een webverzoek kan een opgeslagen voorkeur of gecontroleerde onderhandeling gebruiken; een API moet expliciete en gedocumenteerde velden ontvangen; een proces in de wachtrij moet bij het aanmaken de vereiste ID's opslaan. Een asynchrone taak mag niet aannemen dat zij een sessie, gebruiker of tijdzone erft.
Vertaalbare inhoud en operationele gegevens
Interfaceteksten, communicatiesjablonen en redactionele inhoud hebben een andere levenscyclus dan operationele gegevens. Gebruik stabiele en semantische sleutels, bijvoorbeeld billing.invoice.overdue, in plaats van de oorspronkelijke tekst. Zo kan de formulering worden gewijzigd zonder code, tests of integraties te breken.
Beheerbare inhoud vereist publicatie: een vertaling kan als concept bestaan, goedgekeurd of gepubliceerd zijn. Definieer de terugvalstrategie: aangevraagde taal, basistaal van de organisatie en, waar van toepassing, een zichtbare en gecontroleerde afwezigheid. Een alternatieve vertaling kan aanvaardbaar zijn voor een interne notitie, maar niet noodzakelijk voor contractuele communicatie.
Dupliceer geen volledig operationeel record per taal, tenzij het gegeven gelokaliseerd is. Een product kan een vertaalbare naam en beschrijving hebben, terwijl ID, gewicht, status en beschikbaarheidsregels gemeenschappelijk blijven. Als er een werkelijk commercieel verschil bestaat, modelleer dit dan als variant of beleid, niet als vertaling.
Datums, bedragen, eenheden en afrondingen
Sla tijdstippen eenduidig op en bewaar de tijdzone wanneer de betekenis lokaal is. “De vergadering begint om 09:00” vereist kennis van de zone waarin deze is gedefinieerd; “het evenement vond plaats op dit tijdstip” vereist een absoluut tijdstip. Seizoensgebonden tijdswijzigingen veroorzaken niet-bestaande of herhaalde uren; daarom moet de invoer worden gevalideerd en moet de gekozen oplossing waar van toepassing worden vastgelegd.
Sla voor geld een geheel bedrag in monetaire kleinere eenheden op samen met de valutacode, maar ga niet uit van twee decimalen. De schaal of exponent komt voort uit de metagegevens van de valuta die op de bewerking van toepassing zijn. Sommige valuta's gebruiken een andere schaal dan twee, en historische vereisten of die van een betalingsnetwerk kunnen vereisen dat de effectieve schaal of een versie van de gebruikte regel wordt bewaard.
final class Money {
public function __construct(
public readonly int $minorUnits,
public readonly string $currency,
public readonly int $scale
) {}
}
De schaal maakt een correcte interpretatie van kleinere eenheden mogelijk, maar vervangt geen afrondingsbeleid. Definieer het afrondingsmoment, de toegepaste modus en de contantgeldregel wanneer die bestaat, aangezien afronding voor contant geld kan verschillen van boekhoudkundige afronding. Vermijd float, gelokaliseerde formaten tijdens berekeningen en impliciete conversies.
Hetzelfde patroon geldt voor metingen: bewaar de oorspronkelijke eenheid wanneer die operationele betekenis heeft, normaliseer wanneer de berekening dit vereist en converteer alleen bij invoer of presentatie. Een formulier moet de eenheid en het toegestane formaat aangeven; het mag niet raden of 1,500 één en een half of duizend vijfhonderd betekent.
Architectuur van invoer- en uitvoerstromen
De scheiding van lagen moet zichtbaar zijn in een volledige en herhaalbare stroom:
- Context en invoergegeven vastleggen: organisatie, actor, kanaal, landinstelling, tijdzone en de ontvangen waarde ophalen.
- Het toegestane formaat valideren: verplichte velden, syntaxis, eenheid, valuta, tijdzone en kanaalbeperkingen controleren.
- Normaliseren naar canonieke waarden: gelokaliseerde tekst omzetten naar eenduidige bedragen, datums, eenheden en ID's.
- Het domeingebruiksscenario uitvoeren: expliciete regels en beleidsregels toepassen op canonieke waarden.
- De uitvoer vertalen en formatteren: gepubliceerde berichten kiezen en waarden weergeven voor de ontvanger of het API-contract.
Een API kan besluiten uitsluitend canonieke formaten te accepteren, zoals datums met expliciete zone en gestructureerde bedragen. Een menselijk formulier kan gelokaliseerde formaten accepteren, mits de parseercomponent expliciet is. In beide gevallen ontvangt het domein dezelfde stabiele representatie.
Configureerbaar beleid of een andere bedrijfsregel
Een variatie is doorgaans configureerbaar als zij hetzelfde proces deelt en declareerbare parameters wijzigt, zoals een limiet, een lijst met feestdagen of een berekeningsmethode die door configuratie is gedefinieerd. Die configuratie heeft een schema, versie, verantwoordelijke en tests nodig.
Het verschil wijst op een andere regel wanneer het invarianten, statussen, verantwoordelijkheden, gegevensbronnen of juridische gevolgen wijzigt. In dat geval creëert het verbergen ervan in opties ondoorzichtige configuratie. Modelleer een beleid via een expliciete interface, of een afzonderlijke stroom als het proces werkelijk anders is. Het doel is niet één abstractie af te dwingen, maar te voorkomen dat de volledige applicatie wordt gedupliceerd vanwege een lokaal verschil.
Tests en controlelijst

Tests moeten berekening en representatie verifiëren. Het wijzigen van taal of landinstelling mag een totaalbedrag, een autorisatie of commercieel beleid niet veranderen, tenzij een expliciete vereiste dat bepaalt.
- Test datums bij tijdswijzigingen, met dubbelzinnige en niet-bestaande uren.
- Dek nul- en negatieve bedragen, verschillende schalen, boekhoudkundige afronding en afronding voor contant geld af.
- Controleer toegestane gelokaliseerde invoer en afwijzing van dubbelzinnige formaten.
- Verifieer de terugvalstrategie, afwezigheid van gepubliceerde inhoud en geïnterpoleerde variabelen.
- Voer asynchrone taken zonder sessie uit, met uitsluitend opgeslagen context.
- Test API-contracten met canonieke waarden en formaatmetagegevens wanneer die nodig zijn.
Identificeer vóór het openen van een taal of markt wat werkelijk verandert, scheid de bijbehorende bronnen van waarheid, controleer monetaire en tijdsregels en stel de beschikbaarheid geleidelijk open wanneer de operatie gecontroleerde validatie vereist. Deze discipline maakt uitbreiding van de applicatie mogelijk zonder elke markt in een parallelle versie van het product te veranderen.



