How to Translate Dynamic Content in Rails Using the PTC API

Learn how to use the PTC API to translate dynamic content in your Ruby on Rails (RoR) application. This includes blog posts, product information, and any text stored in your database.

Below, we’ll walk you through the process of translating dynamic content in Rails applications in two parts:

  • First, you’ll learn the three API endpoints individually—how to send content for translation, check its status, and retrieve completed translations.
  • Then, you’ll see how to connect these endpoints into a complete workflow using either callbacks or polling.

Before You Start

This guide assumes you have a Rails application set up with a way to store translations (like Mobility, Globalize, or your own solution).

If you’re starting from scratch or want to see a complete implementation, we’ve built a demo Rails application that shows PTC integration end-to-end. The demo uses:

Set Up PTC and Get Your API Token

To get started, you need a PTC account and API token:

  1. Sign up for PTC. Creating an account is free, and you can translate 20,000 words into 2 languages at no cost. Then, you pay for what you translate.
  2. Create a new project and select API integration.
  3. Copy the API token that PTC generates at the end of project setup. You’ll need this token to authenticate all requests. You can find the same token in your project dashboard under Settings → Manage API tokens.

API Endpoints for Translating Dynamic Content

1

Send Content for Translation

To translate content, use the Create Content Translation endpoint. This schedules your content for translation and returns an ID you’ll use to track progress and retrieve results.

Endpoint:

POST https://app.ptc.wpml.org/api/v1/content_translation

Parameters:

  • data (required) – The content to translate as a hash
  • name (required) – A label for this translation job (for example, "post-123-translation")
  • target_languages (optional) – An array of language codes (for example, ["es", "fr", "de"])
  • callback_url (optional) – A URL where PTC will notify you once translations are

Here’s an example service which starts the translation:

Ruby
require 'net/http'
require 'uri'

module Ptc
  class TranslateService
    def initialize(data:, name: ,target_languages:, callback_url: nil)
      @data = data
      @name = name
      @target_languages = target_languages
      @token = ENV.fetch("PTC_API_TOKEN")
      @callback_url = callback_url
    end

    def call
      translate
    end

    def self.call(**attributes)
      new(**attributes).call
    end

    private
    attr_reader :data, :name, :target_languages, :token, :callback_url

    def translate
      response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
        http.request(request)
      end
      JSON.parse(response.body)
    end

    def body
      {
        data:,
        name:,
        target_languages:,
        callback_url:,
      }.to_json
    end

    def request
      return @request if @request.present?

      @request ||= Net::HTTP::Post.new(uri)
      @request.content_type = "application/json"
      @request.body = body
      @request["Authorization"] = "Bearer #{token}"
      @request
    end

    def uri
      @uri ||= URI.parse("https://app.ptc.wpml.org/api/v1/content_translation")
    end
  end
end

For complete response details, error codes, and additional examples, see the Create Content Translation API documentation.

2

Check the Translation Status

To check if your translation is complete, use the Get Content Translation Status endpoint. This returns the current status and translation progress.

Endpoint:

GET https://app.ptc.wpml.org/api/v1/content_translation/{id}/status

Parameters:

  • id (required) – The unique identifier of the content translation job to check

Example service in Rails:

Ruby
require 'net/http'
require 'uri'

module Ptc
  class GetTranslationStatusService
    def initialize(id:)
      @id = id
      @token = ENV.fetch("PTC_API_TOKEN")
    end

    def call
      get
    end

    def self.call(**attributes)
      new(**attributes).call
    end

    private
    attr_reader :id, :token

    def get
      response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
        http.request(request)
      end
      JSON.parse(response.body)
    end

    def request
      return @request if @request.present?

      @request ||= Net::HTTP::Get.new(uri)
      @request.content_type = "application/json"
      @request["Authorization"] = "Bearer #{token}"
      @request
    end

    def uri
      @uri ||= URI.parse("https://app.ptc.wpml.org/api/v1/content_translation/#{id}/status")
    end
  end
end

The response includes a status field and percentage showing translation progress. For complete response details, see the Get Content Translation API documentation.

3

Retrieve Translations

Once your translation is complete, use the Get Content Translations endpoint to fetch the results. This returns your original content plus translated versions for each target language.

Endpoint:

GET https://app.ptc.wpml.org/api/v1/content_translation/{id}

Parameters:

  • id (required) – The unique identifier of the content translation job to retrieve

Example in Rails:

Ruby
require 'net/http'
require 'uri'

module Ptc
  class GetTranslationService
    def initialize(id:)
      @id = id
      @token = ENV.fetch("PTC_API_TOKEN")
    end

    def call
      get
    end

    def self.call(**attributes)
      new(**attributes).call
    end

    private
    attr_reader :id, :token

    def get
      response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
        http.request(request)
      end
        JSON.parse(response.body)
    end

    def request
      return @request if @request.present?

      @request ||= Net::HTTP::Get.new(uri)
      @request.content_type = "application/json"
      @request["Authorization"] = "Bearer #{token}"
      @request
    end

    def uri
      @uri ||= URI.parse("https://app.ptc.wpml.org/api/v1/content_translation/#{id}")
    end
  end
end

Get Notified When Translations Are Ready

You’ve learned how to send content, check status, and retrieve translations. Now you need to connect these steps so your app automatically knows when to fetch translations.

You can do this by using callbacks (recommended) or by running a job that polls the translation status.

Using Callbacks (Recommended)

When you send content for translation, you can include a callback URL. PTC calls this URL when the translation completes. Your endpoint then fetches and stores the translations.

This is efficient because PTC notifies you immediately.

Ruby
module Api
  class CallbacksController < ActionController::API
    before_action :set_post

    def create
      id = callback_params[:id]

      translation_data = Ptc::GetTranslationService.call(id:)
      translation_data.except("source").each do |locale, data|
        @post.set_translation(locale:, title: data["title"], description: data["description"])
      end

      head :ok
    end

    private

    def set_post
      @post = Post.find(params[:post_id])
    end

    def callback_params
      params.permit([:post_id, :id, :status, :translations_url])
    end
  end
end

Polling the Translation Status (Alternative)

Can’t use callbacks? After sending content for translation, you can queue a background job that repeatedly checks the translation status. The job fetches translations when complete.

This approach is not recommended because it wastes resources and adds unnecessary API calls.

Ruby
class CheckTranslationJob < ApplicationJob

  MAX_ATTEMPTS = 3

  def perform(id:, post_id:, attempt: 0)
    translation = Ptc::GetTranslationStatusService.call(id:)
    if translation["status"] == "completed"
      translation = Ptc::GetTranslationService.call(id:)
      post = Post.find(post_id)
      translation.except("source").each do |locale, data|
        post.set_translation(locale:, title: data["title"], description: data["description"])
      end
    else
      raise "Failed to get translation after #{MAX_ATTEMPTS} attempts" if attempt > MAX_ATTEMPTS

      CheckTranslationJob.set(wait: 1.minute).perform_later(id:, post_id:, attempt: attempt + 1)
    end
  end
end

Start Translating Your Rails Application

You now have everything you need to integrate PTC’s translation API. Create a free account and translate 20,000 words into 2 languages at no cost.

Scroll to Top