Skip to content

Best Practices Guide

This guide outlines the best practices for using the String module effectively in your Drupal projects.

String Organization

1. Namespace Structure

# Good: Clear, hierarchical structure
your_module:
  user:
    profile:
      title: "User Profile"
      description: "Manage your profile settings"
    settings:
      title: "User Settings"
      description: "Configure your account settings"

# Bad: Flat, unclear structure
your_module:
  user_profile_title: "User Profile"
  user_profile_desc: "Manage your profile settings"
  user_settings_title: "User Settings"
  user_settings_desc: "Configure your account settings"
# Good: Logical grouping
your_module:
  form:
    contact:
      title: "Contact Us"
      fields:
        name:
          label: "Your Name"
          placeholder: "Enter your name"
        email:
          label: "Email Address"
          placeholder: "Enter your email"
    feedback:
      title: "Feedback"
      fields:
        message:
          label: "Your Message"
          placeholder: "Enter your feedback"

# Bad: Inconsistent grouping
your_module:
  contact_form_title: "Contact Us"
  contact_name_label: "Your Name"
  contact_name_placeholder: "Enter your name"
  contact_email_label: "Email Address"
  contact_email_placeholder: "Enter your email"
  feedback_form_title: "Feedback"
  feedback_message_label: "Your Message"
  feedback_message_placeholder: "Enter your feedback"

String Definition

1. Using Context

# Good: Clear context for ambiguous strings
your_module:
  actions:
    save:
      default: "Save"
      msgctxt: "form_button"
    delete:
      default: "Delete"
      msgctxt: "form_button"
  navigation:
    save:
      default: "Save"
      msgctxt: "menu_item"
    delete:
      default: "Delete"
      msgctxt: "menu_item"

# Bad: No context for ambiguous strings
your_module:
  save: "Save"
  delete: "Delete"

2. Placeholder Usage

# Good: Clear placeholder names
your_module:
  user:
    greeting:
      default: "Hello, @user_name! Welcome to @site_name."
    profile:
      updated:
        default: "Profile updated by @user_name on @date"

# Bad: Unclear placeholder names
your_module:
  user:
    greeting:
      default: "Hello, @name! Welcome to @site."
    profile:
      updated:
        default: "Profile updated by @user on @time"

3. Plural Forms

# Good: Clear plural forms
your_module:
  items:
    count:
      default: "@count item"
      default_plural: "@count items"
    found:
      default: "1 item found"
      default_plural: "@count items found"

# Bad: Inconsistent plural forms
your_module:
  item_count: "@count item"
  item_count_plural: "@count items"
  items_found: "1 item found"
  items_found_plural: "@count items found"

Code Implementation

1. PHP Usage

// Good: Clear variable names and context
$output = t('your_module.user.greeting', [
  '@user_name' => $user->getDisplayName(),
  '@site_name' => \Drupal::config('system.site')->get('name'),
], ['context' => 'user_welcome']);

// Bad: Unclear variable names and no context
$output = t('your_module.greeting', [
  '@name' => $name,
  '@site' => $site,
]);

2. Twig Template Usage

{# Good: Clear variable names and context #}
{{ 'your_module.user.greeting'|t({
  '@user_name': user.display_name,
  '@site_name': site_name
}, {'context': 'user_welcome'}) }}

{# Bad: Unclear variable names and no context #}
{{ 'your_module.greeting'|t({
  '@name': name,
  '@site': site
}) }}

3. JavaScript Usage

// Good: Clear variable names and context
Drupal.t('your_module.user.greeting', {
  '@user_name': userName,
  '@site_name': siteName
}, {context: 'user_welcome'});

// Bad: Unclear variable names and no context
Drupal.t('your_module.greeting', {
  '@name': name,
  '@site': site
});

Documentation

1. String Comments

# Good: Detailed comments
your_module:
  user:
    profile:
      title:
        default: "User Profile"
        comments:
          - "Displayed in user profile page header"
          - "Used in breadcrumb navigation"
          - "Maximum length: 50 characters"
      description:
        default: "Manage your profile settings"
        comments:
          - "Displayed below the title"
          - "Used in page meta description"
          - "Maximum length: 200 characters"

# Bad: No comments
your_module:
  user:
    profile:
      title: "User Profile"
      description: "Manage your profile settings"

2. Module Documentation

/**
 * @file
 * Contains your_module.string.yml.
 *
 * This file defines all translatable strings for the Your Module.
 * Strings are organized by feature and context.
 *
 * Structure:
 * - user: User-related strings
 *   - profile: Profile management strings
 *   - settings: User settings strings
 * - form: Form-related strings
 *   - contact: Contact form strings
 *   - feedback: Feedback form strings
 */

Performance Considerations

1. String Caching

// Good: Use string caching
$cache_key = 'your_module:strings:' . $language->getId();
$strings = \Drupal::cache()->get($cache_key);

if (!$strings) {
  $strings = $this->loadStrings($language);
  \Drupal::cache()->set($cache_key, $strings, Cache::PERMANENT);
}

// Bad: No caching
$strings = $this->loadStrings($language);

2. Batch Processing

// Good: Use batch processing for large string sets
$batch = [
  'title' => t('Processing strings'),
  'operations' => [
    ['your_module_process_strings', [$strings]],
  ],
  'finished' => 'your_module_process_strings_finished',
];
batch_set($batch);

// Bad: Process all strings at once
foreach ($strings as $string) {
  $this->processString($string);
}

Security Considerations

1. String Sanitization

// Good: Proper string sanitization
$output = t('your_module.user.greeting', [
  '@user_name' => Html::escape($user->getDisplayName()),
  '@site_name' => Html::escape($site_name),
]);

// Bad: No string sanitization
$output = t('your_module.user.greeting', [
  '@user_name' => $user->getDisplayName(),
  '@site_name' => $site_name,
]);

2. Access Control

// Good: Check access before string operations
if ($this->currentUser->hasPermission('manage string export')) {
  $this->exportStrings($strings);
}

// Bad: No access check
$this->exportStrings($strings);

Next Steps