🧑‍🍳 Recipe: Managing Resources with Node.js and Transifex SDK

Hello, code cuisine enthusiasts! I’m Gerardo Núñez, your chef du jour from Transifex’s Customer Success kitchen, and today we’re cooking up some JavaScript magic! This recipe will guide you through creating, updating, and managing resources programmatically - a perfect dish for automating your localization workflow. Grab your coding aprons, and let’s start serving! :fried_egg:

:salt: Ingredients You’ll Need

Before we start coding, ensure you have:

  • Node.js installed on your system
  • A valid Transifex API token
  • Your organization and project slugs are ready

:woman_cook: Cooking Instructions

Step 1: Install Dependencies

First, let’s install the required packages. The Transifex JavaScript SDK is our main ingredient - it provides all the methods we need to interact with the Transifex API. We’ll also install axios, which we’ll use later to download our translated content:

# Install the Transifex JavaScript SDK
npm install @transifex/api

# Install axios for downloading translations
npm install axios

Step 2: Setup Authentication

Before we can start making API calls, we need to set up authentication. The SDK uses an API token to authenticate all requests. You can generate this token from your Transifex user settings page. Once you have it, we’ll import our dependencies and initialize the SDK:

const { transifexApi } = require('@transifex/api');
const axios = require('axios');

transifexApi.setup({ auth: '<YOUR-API-TOKEN>' });

Step 3: Access Your Organization and Project

Now, we need to get references to your organization and project. The SDK uses these models for all subsequent operations. We’ll create a function that retrieves both in one go. Note that we’re using async/await since all SDK operations are asynchronous:

async function getProject() {
  // Get organization model - this is your top-level container
  const organization = await transifexApi.Organization.get({ 
    slug: '<YOUR-ORG-SLUG>' 
  });
  
  // Get project model - where your resources will live
  const projects = await organization.fetch('projects');
  const project = await projects.get({ 
    slug: '<YOUR-PROJECT-SLUG>' 
  });
  
  return { organization, project };
}

Step 4: Create a New Resource

Before creating a resource, we need to specify what type of content it will hold using an i18n format. The KEYVALUEJSON format is great for web and mobile apps as it handles key-value pairs. Here’s how to create a resource with this format:

async function createResource(organization, project) {
  // First, get the i18n format definition
  // KEYVALUEJSON is great for web/mobile apps
  const i18n_format = await transifexApi.i18n_formats.get({
    organization: organization,
    name: 'KEYVALUEJSON'
  });

  // Create the resource with a unique name and slug
  // The slug is used in API calls and URLs
  const resource = await transifexApi.Resource.create({
    name: 'My New Resource',  // Human-readable name
    slug: 'my-new-resource', // URL-friendly identifier
    i18n_format: i18n_format,
    project: project,
  });

  console.log('âś… Resource created successfully!');
  return resource;
}

Step 5: Upload Content

Once we have our resource, we can add content to it. For KEYVALUEJSON format, we’ll create a JSON object with our strings. Each key serves as a unique identifier for a string, and the value is the content to be translated:

async function uploadContent(resource) {
  // Create a JSON object with your strings
  // Keys should be descriptive and unique
  const content = JSON.stringify({
    'welcome_message': 'Welcome to our application!',
    'goodbye_message': 'Thank you for using our app!',
    'error_message': 'Something went wrong. Please try again.'
  });
  
  // Upload using the async upload endpoint
  // This creates a background job to process the content
  await transifexApi.ResourceStringsAsyncUpload.upload({
    resource: resource,
    content: content,
  });
  
  console.log('📤 Content uploaded successfully!');
}

Step 6: Download Translations

After your content has been translated, you can download it in any supported language. The download process is asynchronous - first, you get a URL, and then you download the actual content from that URL:

async function downloadTranslation(resource) {
  // Specify which language you want to download
  // Use language codes like 'fr', 'es', 'de', etc.
  const language = await transifexApi.Language.get({ code: 'fr' });
  
  // Request the download URL
  // This triggers a job to generate the translated file
  const url = await transifexApi.ResourceTranslationsAsyncDownload
    .download({
      resource: resource,
      language: language
    });
  
  // Download the actual content from the provided URL
  // The response will be in the same format as your source
  const response = await axios.get(url);
  console.log('đź“Ą Translated content:', response.data);
  return response.data;
}

Step 7: Delete Resource

Sometimes you need to remove a resource, when a feature is deprecated, or content needs to be reorganized. The SDK provides a simple method for this:

async function deleteResource(resource) {
  // This permanently deletes the resource and all its translations
  // Make sure this is what you want to do!
  await resource.delete();
  console.log('🗑️ Resource deleted successfully!');
}

:dart: Putting It All Together

Now let’s combine all these steps into a complete workflow. This script demonstrates the entire lifecycle of a resource:

async function main() {
  try {
    // First, get our organization and project
    console.log('🔄 Getting organization and project...');
    const { organization, project } = await getProject();
    
    // Create a new resource
    console.log('đź“ť Creating new resource...');
    const resource = await createResource(organization, project);
    
    // Upload our source content
    console.log('📤 Uploading content...');
    await uploadContent(resource);
    
    // Give some time for translation (in real world, this would be done later)
    console.log('⏳ Waiting for translations...');
    await new Promise(resolve => setTimeout(resolve, 5000));
    
    // Download the translated content
    console.log('đź“Ą Downloading translations...');
    await downloadTranslation(resource);
    
    // Clean up by deleting the resource
    console.log('🧹 Cleaning up...');
    await deleteResource(resource);
    
  } catch (error) {
    console.error('❌ Error:', error.message);
  }
}

// Execute the script
main();

:warning: Important Notes

  1. Content must match the specified i18n format
  2. Handle API responses and errors appropriately
  3. Consider implementing rate limiting for large-scale operations

:tada: Next Steps

Now that you’ve mastered the basics of resource management with the JavaScript SDK, you can:

  • Automate resource creation for your projects
  • Build tools for content synchronization
  • Integrate this workflow into your CI/CD pipeline

Stay tuned for more recipes in our Script Chef series! Happy coding! :woman_technologist::man_technologist:

4 Likes