Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Community-sourced default translations #109

Open
2 tasks done
over-engineer opened this issue Jan 16, 2025 · 1 comment
Open
2 tasks done

Community-sourced default translations #109

over-engineer opened this issue Jan 16, 2025 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@over-engineer
Copy link
Member

Is your feature request related to a problem? Please describe.
Default values are only provided for the English translation.

Describe the solution you'd like
Provide default values for more languages. Leverage community-sourced default translations via WordPress.org or external services.

Describe alternatives you've considered
N/A

Checklist

  • I have searched the GitHub issues to ensure this is not a duplicate
  • I have confirmed that this feature is not already available in the latest version of the plugin

Additional context
This feature request is based on the discussion on this topic.

@over-engineer over-engineer added the enhancement New feature or request label Jan 16, 2025
@over-engineer over-engineer self-assigned this Jan 16, 2025
@ppietak
Copy link

ppietak commented Feb 2, 2025

As a quick workaround, I've generated (with Claude) a JS snippet that you can paste into devtools console, and fill the translations (in this case for Polish, but you may easily rework it into any other language with some AI tool)

It worked for me, feel free to use it.

Show the snippet
function getReactFiber(element) {
    const key = Object.keys(element).find(key => 
        key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$')
    );
    return element[key];
}

function getReactProps(element) {
    return Object.keys(element).find(key => key.startsWith('__reactProps$'));
}

const translations = {
    'Consent modal': {
        'Title': 'Zgoda na pliki cookie',
        'Description': 'Cześć, używamy plików cookie, aby zapewnić prawidłowe działanie strony, analizować ruch i wydajność oraz zapewnić funkcje mediów społecznościowych. <button type="button" data-cc="c-settings" class="cc-link">Ustawienia plików cookie</button>',
        'Primary button': 'Zaakceptuj wszystkie',
        'Secondary button': 'Zaakceptuj niezbędne'
    },
    'Settings modal': {
        'Title': 'Preferencje plików cookie',
        'Cookie usage heading': 'Używanie plików cookie 📢',
        'Description': 'Używamy plików cookie, aby zapewnić prawidłowe działanie witryny, analizować ruch i wydajność oraz zapewniać funkcje mediów społecznościowych. Kliknij różne nagłówki kategorii, aby dowiedzieć się więcej i zmienić nasze domyślne ustawienia.',
        'Save settings button': 'Zapisz ustawienia',
        'Accept all button': 'Zaakceptuj wszystkie',
        'Reject all button': 'Odrzuć wszystkie',
        'Close button': 'Zamknij'
    },
    'Cookie table headers': {
        'Cookie name header': 'Nazwa',
        'Cookie domain header': 'Domena',
        'Cookie expiration header': 'Wygaśnięcie',
        'Cookie path header': 'Ścieżka',
        'Cookie description header': 'Opis'
    },
    'Necessary cookies': {
        'Title': 'Niezbędne pliki cookie',
        'Description': 'Te pliki cookie są niezbędne do działania witryny i nie można ich wyłączyć w naszych systemach. Możesz ustawić przeglądarkę tak, aby blokowała lub ostrzegała o tych plikach cookie, ale niektóre części witryny mogą wtedy nie działać.'
    },
    'Analytics cookies': {
        'Title': 'Pliki cookie dotyczące wydajności i analityki',
        'Description': 'Te pliki cookie pozwalają nam analizować wizyty i źródła ruchu, abyśmy mogli mierzyć i poprawiać wydajność naszej witryny. Pomagają nam dowiedzieć się, które strony są najbardziej i najmniej popularne.'
    },
    'Targeting cookies': {
        'Title': 'Pliki cookie do reklam i targetowania',
        'Description': 'Te pliki cookie mogą być ustawiane w naszej witrynie przez naszych partnerów reklamowych i/lub dostawców mediów społecznościowych. Mogą być wykorzystywane przez te firmy do budowania profilu twoich zainteresowań.'
    },
    'Preferences cookies': {
        'Title': 'Pliki cookie funkcjonalności i preferencji',
        'Description': 'Te pliki cookie umożliwiają nam zapewnienie rozszerzonej funkcjonalności i personalizacji poprzez przechowywanie preferencji użytkownika.'
    },
    'More information block': {
        'Title': 'Więcej informacji',
        'Description': 'W przypadku jakichkolwiek pytań dotyczących naszej polityki dotyczącej plików cookie i Twoich wyborów, prosimy o kontakt.'
    }
};

function updateReactInput(input, value) {
    const fiber = getReactFiber(input);
    if (!fiber) return false;

    const propsKey = getReactProps(input);
    if (!propsKey) return false;

    input.value = value;

    const onChange = input[propsKey].onChange;
    if (onChange) {
        const event = new Event('change', { bubbles: true });
        Object.defineProperty(event, 'target', { value: input });
        Object.defineProperty(event, 'currentTarget', { value: input });
        onChange(event);
    }

    if (fiber.stateNode) {
        fiber.stateNode.value = value;
    }

    input.dispatchEvent(new Event('input', { bubbles: true }));
    input.dispatchEvent(new Event('change', { bubbles: true }));

    return true;
}

const panels = document.querySelectorAll('.components-panel__body');
const usedLabels = new Set();
let updateCount = 0;

panels.forEach(panel => {
    const panelTitle = panel.querySelector('.components-panel__body-title')?.textContent.trim() || '';
    const sectionKey = Object.keys(translations).find(key => panelTitle.includes(key)) || '';
    const labels = Array.from(panel.querySelectorAll('.components-base-control__label'));
    
    labels.forEach(label => {
        const labelText = label.textContent.trim();
        const controlId = label.getAttribute('for');
        
        if (controlId && !usedLabels.has(controlId)) {
            const input = document.getElementById(controlId);
            const translation = sectionKey && translations[sectionKey][labelText];
            
            if (input && translation) {
                if (updateReactInput(input, translation)) {
                    updateCount++;
                    usedLabels.add(controlId);
                }
            }
        }
    });
});

console.log(`Translation complete! Successfully updated ${updateCount} fields.`);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants