Set up In-Context Editor

Introduction

To install the PhraseApp In-Context Editor the following steps are required:

  1. Expose the key names of your template
  2. Add our JavaScript snippet to render the editor interface

We provide ready-to-use adapters for common web frameworks. If we do not yet offer an adapter for your technology, you can easily implement it yourself by following the instructions for custom integrations.

Installation

Screencast


This short screencast will show you how to setup the In-Context Editor for your Rails-App in an easy way.

Add the gem

Add the phraseapp-in-context-editor-ruby gem to the environment you want to use the In-Context Editor with:

group :development do
  gem 'phraseapp-in-context-editor-ruby'
end

and install it by executing the bundle command:

$ bundle install

Initialize the gem

Install the phraseapp-in-context-editor-ruby gem by executing the Rails generator:

$ bundle exec rails generate phraseapp_in_context_editor:install --access-token=YOUR_ACCESS_TOKEN --project-id=YOUR_PROJECT_ID
--access-token

You can create and manage access tokens in your profile settings or via the Authorizations API.

--project-id

You can find the ID of your project in your project settings in Translation Center.

This will create an initializer file with some configuration options.

Activate the In-Context Editor

Enable In-Context Editor in your phraseapp_in_context_editor.rb initializer file:

config.enabled = true

Add the JavaScript

Add the JavaScript snippet to your application layout within the <head> section by using the phraseapp_in_context_editor_js helper:

<head>
  ...
  <%= phraseapp_in_context_editor_js %>
  ...
</head>

Done

Open your application in the browser to see the In-Context Editor applied to your app. You can sign in with any user of your PhraseApp account.

Turbolinks

In-Context Editor currently does not work with Turbolinks because Turbolinks will remove all In-Context Editor UI from the page on every page fetch.

To solve this, we recommend disabling Turbolinks when using In-Context Editor by adding the data-no-turbolink attribute to your body tag, e.g.

<body <%= PhraseApp::InContextEditor.enabled? ? "data-no-turbolink" : "" %>>

View phraseapp-in-context-editor-ruby on GitHub

This guide covers integration with angular-phrase an addon for the excellent angular-translate module by Pascal Precht.

Install angular-phrase

Install angular-phrase via Bower (or download it manually):

$ bower install angular-phrase

Add the module to your AngularJS application

Add the angular-phrase module to your existing AngularJS application after loading the angular-translate module:

var myApp = angular.module("myApp", ['pascalprecht.translate', 'phrase']);

Configure

Configure the module:

myApp.value("phraseProjectId", "YOUR-PROJECT-ID");
myApp.value("phraseEnabled", true);
myApp.value("phraseDecoratorPrefix", "{{__");
myApp.value("phraseDecoratorSuffix", "__}}");

You can find the ID of your project in your project settings in Translation Center.

Please see In-Context Editor configuration guide for more information on available configuration options.

Add the JavaScript snippet

Add the phrase-javascript directive within your application, usually best within the <head>:

<phrase-javascript></phrase-javascript>

Done

Open your application in the browser to see the In-Context Editor applied to your app. You can sign in with any user of your PhraseApp account.


More

Create a new environment

We recommend creating a new environment in which In-Context Editor should run. Let's call the new environment translation:

Start by creating a new configuration file:

# app/config/config_translation.yml
imports:
    - { resource: config.yml }
parameters:
    translator.class: Acme\YourBundle\Translation\PhraseTranslator

The environment should be accessible in the browser, so lets create a front controller for it:

# web/app_translation.php
<?php

require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';

use Symfony\Component\HttpFoundation\Request;

$kernel = new AppKernel('translation', false);
$kernel->handle(Request::createFromGlobals())->send();

Extending the Base Translator

You need to override the standard translation method in order to expose the key names to the In-Context Editor:

# Acme/YourBundle/Translation/PhraseTranslator.php
<?php
namespace Acme\YourBundle\Translation;

use Symfony\Bundle\FrameworkBundle\Translation\Translator as BaseTranslator;

class PhraseTranslator extends BaseTranslator
{
    public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null)
    {
        $prefix = "{{__phrase_";
        $suffix = "__}}";

        if (!isset($locale)) {
            $locale = $this->getLocale();
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        if ($domain == 'routes') {
            // Return translated values for 'routes' domain
            return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters);
        } else {
            // Return PhraseApp translation keys for all other domains
            return $prefix.$id.$suffix;
        }
    }
}

Add the JavaScript snippet

To load the In-Context Editor, you need to add the JavaScript snippet to your layout:

# Acme/YourBundle/Resources/views/layout.html.twig
{% if app.environment == 'translation' %}
<script>
window.PHRASEAPP_CONFIG = {
    projectId: "YOUR-PROJECT-ID"
};
(function() {
    var phraseapp = document.createElement('script'); phraseapp.type = 'text/javascript'; phraseapp.async = true;
    phraseapp.src = ['https://', 'phraseapp.com/assets/in-context-editor/2.0/app.js?', new Date().getTime()].join('');
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(phraseapp, s);
})();
</script>
{% endif %}

Done.

Start translating your app by accessing your front controller in the browser!

The code in this tutorial was created by Malte Marx from marxbeck

More

Create a new environment

We recommend creating a new environment in which In-Context Editor should run. Let's call the new environment translation:

Start by creating a new configuration file:

# app/config/config_translation.yml
imports:
   - { resource: config.yml }

The environment should be accessible in the browser, so lets create a front controller for it:

# web/app_translation.php
<?php

use Symfony\Component\HttpFoundation\Request;

$loader = require __DIR__.'/../app/autoload.php';

$kernel = new AppKernel('translation', true);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

Extending the Base Translator

You need to override the standard translation method in order to expose the key names to the In-Context Editor:

# src/AppBundle/Translation/PhraseTranslator.php
<?php
namespace AppBundle\Translation;

use Symfony\Bundle\FrameworkBundle\Translation\Translator as BaseTranslator;

class PhraseTranslator extends BaseTranslator
{
   public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null)
   {
       $prefix = "{{__phrase_";
       $suffix = "__}}";

       if (null === $domain) {
           $domain = 'messages';
       }

       // Return ID of translation key with pre- and suffix for PhraseApp
       return $prefix.$id.$suffix;
   }
}

Creating Compiler Pass

Now, to make sure the class is always overridden when your bundle is used, you should use a compiler pass

# src/AppBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php
<?php
namespace AppBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class OverrideServiceCompilerPass implements CompilerPassInterface
{
   public function process(ContainerBuilder $container)
   {
       $definition = $container->getDefinition('translator.default');
       $definition->setClass('AppBundle\Translation\PhraseTranslator');
   }
}

When using separate compiler passes, you need to register them in the build() method of the bundle class:

# src/AppBundle/AppBundle.php
<?php

namespace AppBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use AppBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass;

class AppBundle extends Bundle
{
   public function build(ContainerBuilder $container)
   {
       parent::build($container);

       if($container->getParameter("kernel.environment") == 'translation') {
           $container->addCompilerPass(new OverrideServiceCompilerPass());
       };
   }
}

Add the JavaScript snippet

To load the In-Context Editor, you need to add the JavaScript snippet to your layout (don't forget to set your project id):

# src/YourBundle/Resources/views/layout.html.twig
{% if app.environment == 'translation' %}
<script>
window.PHRASEAPP_CONFIG = {
   projectId: "YOUR-PROJECT-ID"
};
(function() {
   var phraseapp = document.createElement('script'); phraseapp.type = 'text/javascript'; phraseapp.async = true;
   phraseapp.src = ['https://', 'phraseapp.com/assets/in-context-editor/2.0/app.js?', new Date().getTime()].join('');
   var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(phraseapp, s);
})();
</script>
{% endif %}

Done.

Start translating your app by accessing your front controller in the browser!

The code in this tutorial was created by Malte Marx from marxbeck

More

Add the package

Install the django-phrase package with pip:

$ pip install django-phrase

And add phrase to the list of installed apps:

INSTALLED_APPS = (
    'phrase',
)

Extend the template

You can now use the phrase_i18n template tag in your templates:

{% load phrase_i18n %}

Note: You have to load phrase_i18n after you load ì18n in order to let django-phrase override the translation methods.

Add the JavaScript snippet

Add the JavaScript snippet to your base layout file. This should go inside the <head> section of your template file:

{% phrase_javascript %}

Configuration

You can configure the In-Context Editor in your settings by using these options:

PHRASE_ENABLED = True
PHRASE_PROJECT_ID = 'YOUR_PROJECT_ID'
PHRASE_PREFIX = '{{__'
PHRASE_SUFFIX = '__}}'

Done

Open your application in the browser to see the In-Context Editor applied to your application. You can sign in with any user of your PhraseApp account.


More

Copy the source code

Make sure the package com.phraseapp.incontexteditor is available in your app. You can check it out on GitHub.

Configure your Project ID

Set the correct project ID and adjust the remaining configuration in PhraseAppConfiguration.class.

Apply PhraseApp as your MessageSource

In order to render all translations through PhraseApp, you must add the bean to your application:

@Bean
@Conditional(PhraseAppEnabledCondition.class)
public MessageSource messageSource() {
    return new PhraseAppMessageSource();
}

Add the Javascript

Provide the required Javascript helper in your templates by exposing the helper as a bean:

@Bean
public PhraseAppJavascriptHeader phraseAppJavascriptHeader() {
    return new PhraseAppJavascriptHeader();
}

and then adding the script tag to your templates, within the page head:

<head>
    <script th:utext="${@phraseAppJavascriptHeader.getHeader()}"></script>
</head>

Restart the application and sign in with your PhraseApp user credentials.

More

If there is no ready-to-use adapter for your technology yet, you can easily implement it yourself following the instructions for custom integrations.


More resources