pt-BR means Brazilian Portuguese: how it differs from pt-PT and pt

pt-BR means Portuguese as it is written in Brazil. The tag comes in two parts: pt is the subtag for the Portuguese language, BR is the region subtag for Brazil. pt-PT is the same construction for Portugal, and by convention it stands for European Portuguese in general. Ask the Unicode CLDR data that browsers and phones ship with for the English name of each tag and it answers Brazilian Portuguese for pt-BR and European Portuguese for pt-PT. A bare pt is Portuguese with no region stated, which is not the same thing as neutral Portuguese.

That last distinction is where the real trouble sits. In that same CLDR data, which browsers, phones and game engines also use to format dates and numbers, pt resolves to pt-Latn-BR: Latin script, Brazil. Any recent Node build will show you this, because Intl.Locale for pt, maximized, returns pt-Latn-BR. So a build tagged pt does not hand a player in Portugal neutral Portuguese. It hands them Brazilian conventions, and it records nowhere that this was a decision anybody made.

The two varieties are close enough that a translator working in one reads the other without effort, which is exactly why they get merged. If you are here because a store language list, a settings menu or a filename put pt-BR in front of you, the rest of this article settles four things: how to write the tag, what each store and engine calls these two varieties, which words and formats actually differ, and how to choose when the budget covers one.

Write the tag as pt-BR or pt-PT, and know what a bare pt becomes

The canonical form puts the language subtag in lower case and the region subtag in upper case. Case is not significant when a tag is parsed, but tools normalize and mixed spellings in a repository make a search unreliable. Passing pt-br, pt-pt and pt through the canonicalizer in the Intl API returns pt-BR, pt-PT and pt, so casing is one command to settle rather than a matter of house style.

The region subtag is a two-letter ISO 3166-1 country code, which is why pt-PT looks redundant and is not: Portugal is the country, European Portuguese is the written standard. Portuguese is also official in Angola, Mozambique and several other countries, and their tags exist too, pt-AO and pt-MZ among them. On the group separator those follow Portugal rather than Brazil, using a no-break space, but they are not aliases for pt-PT: pt-AO separates a four-digit number where pt-PT leaves it unseparated. Using pt-PT as shorthand for European Portuguese is a working convention, not a claim that Portugal is the only alternative to Brazil.

The practical cost of a bare pt shows up in locale matching. When a player's system asks for pt-PT and your build ships only pt, a lookup-style matcher truncates the request to pt and accepts it. The screen fills with text, nothing errors, and a player in Lisbon reads Brazilian Portuguese with Brazilian number formatting. That is not a failure anything will report to you. For how the subtags are structured, see BCP 47 language tags; for where the formatting data itself comes from, see Unicode CLDR explained.

The same two varieties under four different spellings

Nothing on this list disagrees about which two varieties exist. They disagree about how to spell them, and the spellings are near enough to each other to fail silently.

Two of these rows cause most of the real breakage. The underscore form is what gettext, POSIX locale names and Java use, so pt_BR and pt-BR end up in the same project and a string comparison between them fails. Android adds the r prefix on the region qualifier, so a directory named values-pt-BR is not a valid qualifier at all; confirm the exact form against the official resource-qualifier documentation. The resource qualifiers are covered in Android strings.xml, and the underscore convention in the gettext PO file format.

Steam is the outlier: its API language codes are English words rather than tags, so Brazilian Portuguese is brazilian and European Portuguese is portuguese. The Steamworks page on localization and languages holds the authoritative table, listing the English name, the native name, the API language code and a separate Web API code side by side. Copy those strings from that table rather than deriving them, and keep the mapping from each platform's name to your own locale identifier in one data file instead of a chain of conditionals. What a store listing commits you to is covered in Steam supported languages and what counts.

                              Brazil                Portugal / Europe
BCP 47, canonical             pt-BR                 pt-PT
Underscore form               pt_BR                 pt_PT
  (gettext .po, POSIX locale names, Java Locale)
Android resource directory    values-pt-rBR         values-pt-rPT
Unity, Unreal culture name    pt-BR                 pt-PT
App Store Connect locale      pt-BR                 pt-PT
Google Play Console locale    pt-BR                 pt-PT
Steam API language code       brazilian             portuguese

Copy every row from that platform's own language table or resource-qualifier
reference; never reconstruct one from the tag. Store-facing labels also differ
in wording between platforms and have changed over time.

The words that differ are the words in your menu

The 1990 Orthographic Agreement removed a set of spelling differences between the two standards, and it gets cited as though it had merged them. It did not touch vocabulary or grammar, and vocabulary is where interface text diverges. The differences are not obscure either. Several of them are the words on a pause menu.

The first four rows are the ones that decide how a game reads, because file, save, screen and user appear in menus, settings and error messages rather than in dialogue. A Brazilian build labels the menu item salvar; a European build labels it guardar. Neither word is wrong in the other country, and a reader in Portugal understands salvar perfectly well. It simply marks the text as written for somewhere else, in the one place every player looks.

Grammar diverges too, in a construction that lands in status text. The present progressive in Brazil uses a gerund, estou fazendo for I am doing. European Portuguese normally uses a followed by the infinitive, estou a fazer. An autosave or loading message built from one pattern reads as foreign under the other.

Address form is the third axis, and the one to decide before translation starts. European Portuguese distinguishes tu, the informal singular, from você, which is more distant and takes third-person verb forms. Brazilian Portuguese uses você as the ordinary second person across most of the country. So a tutorial written to sound neutrally friendly in Brazil can read as stiff or dated in Portugal. Fix the choice per variety in the glossary rather than leaving it to whoever translates the next batch.

English         Brazil (pt-BR)     Portugal (pt-PT)
file            arquivo            ficheiro
save            salvar             guardar
screen          tela               ecrã
user            usuário            utilizador
mouse           mouse              rato
mobile phone    celular            telemóvel
bus             ônibus             autocarro
train           trem               comboio

Number, date and plural differences you can verify yourself

Everything in this section came out of the Intl API in Node 22, which reads Unicode CLDR data, version 46 in that build. Naming the source matters because you can run the same calls and compare the output rather than trust a summary of it.

Numbers differ in the group separator: Brazilian Portuguese groups with a period, European Portuguese with a no-break space, and both use a comma for the decimal mark. There is a second difference that is easy to miss. European Portuguese does not group a four-digit number at all, starting only at five digits, so the same value prints with a separator in one variety and without one in the other. Currency symbol position differs as well, before the amount in Brazil and after it in Portugal.

Dates are less different than people expect. The long form is identical in both, 9 de março de 2026, sharing day-month-year order and lower-case month names. Two shorter forms are not identical: the short date carries a four-digit year in Brazil and a two-digit year in Portugal, and the medium date has a different shape entirely.

The abbreviated weekday is the one that breaks a layout. Asking for a short weekday name in European Portuguese returns a whole word, domingo and segunda rather than an abbreviation; the long name only adds the suffix, segunda-feira. So a calendar or a daily-reward strip built around Brazil's three letters and a period overflows its columns when the same screen renders for Portugal. CLDR's own phrasing diverges too, which is worth seeing once: a time two weeks ahead is em 2 semanas in Brazil and dentro de 2 semanas in Portugal.

The structural difference is plural selection at zero. Brazilian Portuguese puts 0 in the one category, European Portuguese puts it in other, so 0 item is right for Brazil and 0 itens for Portugal. A counted string therefore cannot share a plural block across both varieties. If your strings go through ICU MessageFormat, the pt-BR and pt-PT entries have genuinely different bodies, not the same body with different words in it.

Numbers and currency
  pt-BR  1234567.89  ->  1.234.567,89
  pt-PT  1234567.89  ->  1 234 567,89   separator is U+00A0, a no-break space
  pt-BR     1234.5   ->  1.234,5
  pt-PT     1234.5   ->  1234,5         no grouping below five digits
  pt-BR     1234.5   ->  R$ 1.234,50    currency BRL, symbol first
  pt-PT     1234.5   ->  1234,50 €      currency EUR, symbol last

Dates
  dateStyle         pt-BR                  pt-PT
  short             09/03/2026             09/03/26
  medium            9 de mar. de 2026      09/03/2026
  long              9 de março de 2026     9 de março de 2026
  short weekday     dom. seg. ter.         domingo segunda terça

Plural category of zero
  pt-BR  select(0)  ->  "one"    so: 0 item
  pt-PT  select(0)  ->  "other"  so: 0 itens

Picking one variety, or shipping both without doubling the work

If the budget covers one Portuguese, the usual answer is pt-BR, and the reason is population: Brazil's Portuguese-speaking population is far larger than Portugal's, so the same spend reaches more readers. Treat that as the default rather than the rule, and look at your own numbers first, since regional wishlist and traffic data will tell you whether Portugal is a real segment for your game. Where to find those figures is covered in reading regional wishlist data.

If you ship both, the saving is real but it is not in the translation. What transfers is structure: string keys, placeholder shapes, the glossary's format, the review checklist, the screenshots you send as context. What does not transfer is the glossary's contents, the address-form decision, and the plural block for counted strings. Budget the second variety as an adaptation pass by a native speaker of that variety, not as a find-and-replace over the first.

The decision has the same shape as the Spanish one, and for the same reasons: two large written standards, one much larger market, and vocabulary divergence wide enough to be noticed. That case is worked through in Latin American Spanish versus Spain Spanish.

When you commission the work, write pt-BR or pt-PT in the request. Portuguese on its own invites a guess, and a translator who normally works for a European client will guess differently from one who works for a Brazilian studio. Put the variety in the kit next to the audience, the platform and the character limits; preparing a localization kit lists what else belongs in there.

  • Tag every file pt-BR or pt-PT, and treat a bare pt in the repository as a bug, because CLDR resolves it to Brazil
  • Keep one data file mapping each platform's spelling to your locale identifier, and test that every name you can receive lands somewhere
  • Write the glossary per variety, starting with arquivo and ficheiro, salvar and guardar, tela and ecrã, usuário and utilizador
  • Decide tu or você per variety before the first batch goes out for translation
  • Give counted strings their own plural block per variety, because zero is singular in Brazil and plural in Portugal
  • Before release, check number output at four digits and weekday labels in any narrow column
  • On a store, confirm which language slot you are filling; publishing a Brazilian translation under a general Portuguese entry advertises support to Portugal that you did not ship

Related articles