Localization

Open Graph supports internationalization (i18n) of actions and objects for use in multiple languages. Once an app’s text strings are in the Facebook system for translation, you can translate the strings or leverage the community or people using the app for translation. (People can help translate using the Translations app.) Once translated, text strings must go through the same approval process as other translated strings. That is, the language administrators and owners must agree that the translations meet with Facebook guidelines.


Self-Hosted Objects

Self-Hosted Open Graph Objects are annotated web pages with a set of meta tags that provide property values. Object properties include the title, description and any custom properties. Objects are connected to people using apps via actions, and when this happens, an object appears in timeline, news feed and ticker.

Object property values can be stored in multiple languages. To make sure your object is scraped in multiple languages, make sure to do either of the following:

  1. Call the Graph API to update the object URL with the locale parameter.
  2. Specify an array of og:locale:alternate meta tags to define which locales you support.

The Open Graph Object Crawler will include fb_locale parameter in the URL (for example, ?fb_locale=en_US) and also in the X-Facebook-Locale header. If the app has localized text for that language, it should return the <meta> tags with strings matching the header. Facebook stores those strings hashed by the language.

To take advantage of this, start by adding the og:locale meta tag markup to your web pages. It is an optional property, and it will accept one of the Facebook specific locales. To ensure that an object supports a language you should either scrape it via the Graph API call (add the <code>locale</code> parameter to the object scrape api or add the og:locale:alternate meta tag). You can specify multiple og:locale:alternate tags if you support different languages.

<html>
  <head>
    <meta property="og:locale" content="en_US" />
    <meta property="og:locale:alternate" content="fr_FR" />
    <meta property="og:locale:alternate" content="es_ES" />
    <meta property="og:title" content="Beef steak" />
    ...

Then, when your object is crawled by Facebook (see Using the Object API for details on publishing an object to Open Graph), we'll add a new HTTP header called X-Facebook-Locale and the fb_locale URL parameter. This should be considered a hint for what locale the app is looking for. By looking at this parameter, your app should return the Open Graph meta tags in the requested locale with the og:locale meta tag now echoing what was requested. (If your app doesn't have data in this locale, you can return a "default" version where the og:locale isn't specified, or data for another locale.)

<html>
  <head>
    <meta property="og:locale" content="fr_FR" />
    <meta property="og:locale:alternate" content="en_US" />
    <meta property="og:locale:alternate" content="es_ES" />
    <meta property="og:title" content="Bifteck" />
    ...

The og:url and og:type in the meta data must be the same regardless of the fb_locale parameter. Note that this means the og:url field should not reflect the fb_locale parameter. Other meta tags for localized objects can be different.

Apps can also request a recrawl by passing the locale attribute to the Graph API’s scrape endpoint via HTTP POST. For example:

Crawl in English:

POST https://graph.facebook.com?id=http://example.com/movie/inception&amp;scrape=true&amp;locale=en_US

Crawl in French:

POST https://graph.facebook.com?id=http://example.com/movie/inception&amp;scrape=true&amp;locale=fr_FR

To scrape an object for more than one language, you can specify the languages comma-separated in the locale attribute. For example:

Crawl in English, French, Spanish, and Portuguese:

POST https://graph.facebook.com?id=http://example.com/movie/inception&amp;scrape=true&amp;locale=en_US,fr_FR,es_LA,pt_BR

When an object property changes, or when an app decides to add a new language to support, you should also make the Graph API call for each language supported to update the object definitions inside Facebook.


Hosted Objects

Hosted Objects are created via Facebook's Object API. They are hosted on Facebook's servers instead of being hosted on your server.

It's possible to add a localization to an object after it's been created. You create a localization for an object by posting a new object to the ID of the created object with a locale field in the object.

For example, if you created a custom object in Spanish:

curl -X POST \
-F 'object={"locale":"es_ES",
            "title":"mi objeto",
            "description":"mi descripción", 
            "data": { "obj_extra":"mi información" } }' \
"https://graph.facebook.com/$APPID/objects/testme_like_app:foo?access_token=$APPID|$APPSECRET"

It returns an ID:

{"id":"645752348782873"}

You can then use this ID to create an English version of the object:

curl -X POST \
-F 'object={"locale":"en_US",
            "title":"my english object",
            "description":"my english description"}' \
"https://graph.facebook.com/645752348782873?access_token=$APPID|$APPSECRET"

This will return the object you just created:

{
  "type":"testme_like_app:foo",
  "title":"my english object",
  "locale":{"locale":"en_us"},
  "description":"my english description",
  "updated_time":"2013-08-12T23:20:57+0000",
  "id":"645752348782873",
  "application":{
    "id":"384179895015798",
    "name":"Test Like App",
    "url":"http:\/\/www.facebook.com\/apps\/application.php?id=384179895015798"
  }
}

Once you've created two locales you can request either version with the locale parameter. Here are the two versions of the object:

curl -X GET \
"https://graph.facebook.com/645752348782873?access_token=$APPID|$APPSECRET&amp;locale=es_ES"

{
  "id":"645752348782873",
  "type":"testme_like_app:foo",
  "title":"mi objeto",
  "locale": {
    "locale":"es_es"
  },
  "description":"mi descripci\u00f3n",
  "updated_time":"2013-08-12T23:18:40+0000",
  "created_time":"2013-08-12T23:18:40+0000",
  "application": {
    "id":"384179895015798",
    "name":"Test Like App",
    "url":"http:\/\/www.facebook.com\/apps\/application.php?id=384179895015798"},
  "is_scraped":false
}
curl -X GET \
"https://graph.facebook.com/645752348782873?access_token=$APPID|$APPSECRET&amp;locale=en_US"

{
  "id":"645752348782873",
  "type":"testme_like_app:foo",
  "title":"my english object",
  "locale": {
    "locale":"en_us"
  },
  "description":"my english description",
  "updated_time":"2013-08-12T23:20:57+0000",
  "created_time":"2013-08-12T23:20:57+0000",
  "application": {
    "id":"384179895015798",
    "name":"Test Like App",
    "url":"http:\/\/www.facebook.com\/apps\/application.php?id=384179895015798"},
  "is_scraped":false
}

If you change an object, for example change its title or description, the localizations are not invalidated. You must update each localization separately.

The list of supported languages is documented in our documentation on localizing on Facebook.

You can localize app or user-owned objects.


Actions

Action types are eligible to be translated immediately by Facebook. To set up your app for translation, see our Internationalization Guide.

Action properties are not translated. For example, if an app has a review action with the review_text custom property and someone using it posts the review_text in English, a French viewer will see the review_text in English.


News feed and ticker

The text of app stories are eligible for translation immediately. Read the Internationalization Guide for details.

Each feed story has a corresponding template that includes placeholders for the full name of someone using an app ("James Sinclair" as opposed to the username "Jsinc") and the object titles. For locales where Facebook supports gender variations, the appropriate variation should be supplied to avoid oddities with verb conjugations. Prepositions like those used for attribution, for example “on Netflix” or “on ClimbOn”, will be part of the feed story that is translated. Here's an example story for translation:

{subject} watched {object} on Netflix
{subject} watched {object} and 3 other movies on Netflix

In the example, “subject” is the username and “object” is the object’s title and can optionally be translated by the app that owns or publishes the object. Note that in the aggregated story the action “watched” and object “movies” were provided by the app developer via the Open Graph development tool.


Pluralization

Template text supports pluralization so that developers can write sentences that include cardinality like “Listened once” or “Listened 57 times”. This is achieved through the following:

“Listened {count | pluralize(“once”, “%d times”)}”

This is converted into two translatable sentences:

  1. Listened once
  2. Listened {count} times

More information about localization

For a summary of the tools Facebook provides developers for localization and translation, see Facebook Localization Tools. Localizing text from Open Graph objects and actions relies on the same basic tools and techniques described there.

Best practices

My app is used in only one locale

Always put the og:locale for the target locale, like en_US. And go to the App Center Translation Panel --> Dashboard tab and uncheck all the locales but the one your app uses. To get to this tab, go to the app dashboard, select the app you want to work on, click "Edit App" and click Localize in the left-hand column. Click the link for Advanced Options, then select the Dashboard tab.

Different locales for the same object

When a request comes in, look at the "X-Facebook-Locale" header, and serve localized OG data for the object based on that locale. Ensure that you include the <code>og:locale</code> property and that it matches the data it's associated with.

What if I don't have data for the locale specified via "X-Facebook-Locale" header?

You can do one of two things:

  1. Output a generic version that does not specify the <code>og:locale</code> property.
  2. Output some other locale. If you don't have a "generic", and always specify a locale, we'll choose a best-match locale for people using the app based on the locales you provide.

What if I don't see a string from my app that I just added or changed? What if I see strings that my app no longer uses?

Since we extract strings from your app statically, when you add or update strings in your app you need to click the Delete and re-import all strings link within the translation dashboard at https://www.facebook.com/translations/admin/?app={YOUR_APP_ID}.

Note: this will delete all previously extracted strings from the app (or strings that were uploaded or extracted from FBML) and re-import the current strings from the app. Since FBML is being deprecated, those strings will not be imported. This will not remove translations for strings that have been previously extracted and translated, if you re-import the same strings with the same descriptions the translations will still be present.

Since this deletes old strings before re-importing the current ones you can use this method to remove left-over strings (that are no longer used after you've edited or deleted an action type, changed the application name or description and so on).

Impact of changing the app name

If you change your app name, you will need to re-translate any strings using the app name. This may be a large level of effort depending on how many strings you have that will be affected. To re-translate, after changing the app name, perform the Delete and re-import all strings action as described above. Next, re-translate the strings as needed.

Localization best practices

  • If you are locale aware, always specify a og:locale property. When you write out your other Open Graph properties such as og:title, as you're already aware of a locale, make sure to output the og:locale property. Look for the "X-Facebook-Locale" header, and output for that locale if you have that data.
  • The verb that corresponds to an action type should be a real English verb, and the text for it should not include any other words. (Counter examples include "just ate" and "is about to eat".) Any other verbs might cause internationalization issues, either because they are words invented in English ("awesom’d") that don't have a reasonable equivalent in many languages, or because the English sentences themselves make no sense because of the way they were generated out of parts that are not just a verb.