Support Log in

38. Security Considerations

Developer Guide
Prefer video? Watch the Lang Forge tutorials 9 short guides covering every feature Watch

Security best practices when building multilingual sites with Lang Forge.

Input Sanitization for Language Parameters

php
/**
 * Always validate language codes before using them.
 * Lang Forge's internal functions do this automatically,
 * but if you handle language codes manually, validate them.
 */
function theme_validate_language($code) {
    // Language codes should be 2-5 characters, lowercase, letters and hyphens only
    if (!preg_match('/^[a-z]{2,5}$/', $code)) {
        return false;
    }

    // Check against active languages
    $languages = lf_get_languages();
    return isset($languages[$code]);
}

// Usage in a custom endpoint
add_action('rest_api_init', function () {
    register_rest_route('mytheme/v1', '/switch-lang', [
        'methods'  => 'POST',
        'callback' => function (WP_REST_Request $request) {
            $lang = sanitize_text_field($request->get_param('lang'));

            if (!theme_validate_language($lang)) {
                return new WP_Error('invalid_lang', 'Invalid language code', ['status' => 400]);
            }

            // Proceed with language switch
            $core = LF_Core::instance();
            $url = $core->get_language_url($lang);
            return rest_ensure_response(['redirect' => $url]);
        },
        'permission_callback' => '__return_true',
    ]);
});

Escaping Translated Content

php
// ALWAYS escape translated strings before output.
// Translations are entered by humans and could contain malicious content.

// Correct - escaped
echo esc_html__('Welcome', 'theme');

// Correct - escaped attribute
echo '<input placeholder="' . esc_attr__('Search...', 'theme') . '">';

// Correct - escaped URL
echo '<a href="' . esc_url($core->get_language_url('en')) . '">English</a>';

// WRONG - unescaped (vulnerable to XSS)
// echo __('Welcome', 'theme');

REST API Permission Checks

php
// Lang Forge's REST endpoints check for edit_posts or manage_options.
// If building custom endpoints that expose translation data publicly,
// be careful not to leak draft/private post information.
// Write endpoints should also validate the target language against the
// current effective plan, not just the raw lf_active_languages option.

register_rest_route('mytheme/v1', '/translations/(?P<id>d+)', [
    'methods'  => 'GET',
    'callback' => function ($request) {
        $post_id = intval($request->get_param('id'));
        $post = get_post($post_id);

        // Only return data for published posts to unauthenticated users
        if (!$post || $post->post_status !== 'publish') {
            if (!current_user_can('edit_posts')) {
                return new WP_Error('not_found', 'Post not found', ['status' => 404]);
            }
        }

        $translations = lf_get_post_translations($post_id);
        // Filter out non-published translations for public requests
        if (!current_user_can('edit_posts')) {
            foreach ($translations as $lang => $trans_id) {
                if (get_post_status($trans_id) !== 'publish') {
                    unset($translations[$lang]);
                }
            }
        }

        return rest_ensure_response($translations);
    },
    'permission_callback' => '__return_true',
]);

Nonce Verification for Language Forms

php
// When building custom forms that include language selection,
// always use nonces to prevent CSRF attacks.

// Form output
echo '<form method="post">';
wp_nonce_field('lf_language_action', 'lf_language_nonce');
echo '<select name="target_language">';
foreach (lf_get_languages() as $code => $lang) {
    echo '<option value="' . esc_attr($code) . '">' . esc_html($lang['name']) . '</option>';
}
echo '</select>';
echo '<button type="submit">Create Translation</button>';
echo '</form>';

// Form processing
if (isset($_POST['lf_language_nonce']) && wp_verify_nonce($_POST['lf_language_nonce'], 'lf_language_action')) {
    $target_lang = sanitize_text_field($_POST['target_language']);
    // Process the form...
}

Forge AI Assistant Online

Hi! I'm the Lang Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs