<commit_before>package FixMyStreet::Roles::Translatable;

use Moo::Role;

sub translate_around {
    my ($orig, $self) = (shift, shift);
    my $fallback = $self->$orig(@_);
    (my $col = (caller(2))[3]) =~ s/.*:://;
    $self->_translate($col, $fallback);
}

sub translate_column {
    my ($self, $col) = (shift, shift);
    my $fallback = $self->$col(@_);
    $self->_translate($col, $fallback);
}

sub _translate {
    my ($self, $col, $fallback) = @_;

    my $schema = $self->result_source->schema;
    my $table = lc $self->result_source->source_name;
    my $id = $self->id;

    # Deal with the fact problem table has denormalized copy of category string
    if ($table eq 'problem' && $col eq 'category') {
        my $body_id = $self->bodies_str_ids->[0];
        return $fallback unless $body_id && $body_id =~ /^[0-9]+$/;
        my $contact = $schema->resultset("Contact")->find( {
            body_id => $body_id,
            category => $fallback,
        } );
        return $fallback unless $contact; # Shouldn't happen, but some tests
        $table = 'contact';
        $id = $contact->id;
    }

    if (ref $schema) {
        my $translation = $schema->resultset('Translation')->find({
            lang => $schema->lang,
            tbl => $table,
            object_id => $id,
            col => $col
        });
        return $translation->msgstr if $translation;
    } else {
        warn "Can't use translation on this call to $table.$col";
    }
    return $fallback;
};

# These next two functions (translation_for and and_translation_for) are
# convenience methods for use in the translation interface in the admin.
# They shouldn't be used else where as they don't take account of things
# like denormalised strings (e.g report category)
sub translation_for {
    my ($self, $col, $lang) = @_;

    my $schema = $self->result_source->schema;

    my $props = {
        tbl => lc $self->result_source->source_name,
        object_id => $self->id,
        col => $col
    };

    if ($lang) {
        $props->{lang} = $lang;
    }

    my $translations = $schema->resultset('Translation')->search($props);

    return $lang ? $translations->first : $translations;
}

sub add_translation_for {
    my ($self, $col, $lang, $msgstr) = @_;

    my $schema = $self->result_source->schema;

    my $props = {
        tbl => lc $self->result_source->source_name,
        object_id => $self->id,
        col => $col,
        lang => $lang,
        msgstr => $msgstr,
    };

    my $translation = $schema->resultset('Translation')->update_or_create(
        $props,
        { key => 'translation_tbl_object_id_col_lang_key' }
    );

    return $translation;
}

1;
<commit_msg>Remember translation lookup for request remainder.<commit_after>package FixMyStreet::Roles::Translatable;

use Moo::Role;

has _translated  => (is => 'rw');

sub translated {
    my $self = shift;
    $self->_translated or $self->_translated({});
}

sub translate_around {
    my ($orig, $self) = (shift, shift);
    my $fallback = $self->$orig(@_);
    (my $col = (caller(2))[3]) =~ s/.*:://;
    $self->_translate($col, $fallback);
}

sub translate_column {
    my ($self, $col) = (shift, shift);
    my $fallback = $self->$col(@_);
    $self->_translate($col, $fallback);
}

sub _translate {
    my ($self, $col, $fallback) = @_;

    my $schema = $self->result_source->schema;
    my $table = lc $self->result_source->source_name;
    my $id = $self->id;
    my $lang = $schema->lang || '';

    my $translated = $self->translated->{$col}{$lang};
    return $translated if $translated;

    # Deal with the fact problem table has denormalized copy of category string
    if ($table eq 'problem' && $col eq 'category') {
        my $body_id = $self->bodies_str_ids->[0];
        return $fallback unless $body_id && $body_id =~ /^[0-9]+$/;
        my $contact = $schema->resultset("Contact")->find( {
            body_id => $body_id,
            category => $fallback,
        } );
        return $fallback unless $contact; # Shouldn't happen, but some tests
        $table = 'contact';
        $id = $contact->id;
    }

    if (ref $schema) {
        my $translation = $schema->resultset('Translation')->find({
            lang => $lang,
            tbl => $table,
            object_id => $id,
            col => $col
        });
        $fallback = $translation->msgstr if $translation;
    } else {
        warn "Can't use translation on this call to $table.$col";
    }
    $self->translated->{$col}{$lang} = $fallback;
    return $fallback;
};

# These next two functions (translation_for and and_translation_for) are
# convenience methods for use in the translation interface in the admin.
# They shouldn't be used else where as they don't take account of things
# like denormalised strings (e.g report category)
sub translation_for {
    my ($self, $col, $lang) = @_;

    my $schema = $self->result_source->schema;

    my $props = {
        tbl => lc $self->result_source->source_name,
        object_id => $self->id,
        col => $col
    };

    if ($lang) {
        $props->{lang} = $lang;
    }

    my $translations = $schema->resultset('Translation')->search($props);

    return $lang ? $translations->first : $translations;
}

sub add_translation_for {
    my ($self, $col, $lang, $msgstr) = @_;

    my $schema = $self->result_source->schema;

    my $props = {
        tbl => lc $self->result_source->source_name,
        object_id => $self->id,
        col => $col,
        lang => $lang,
        msgstr => $msgstr,
    };

    my $translation = $schema->resultset('Translation')->update_or_create(
        $props,
        { key => 'translation_tbl_object_id_col_lang_key' }
    );

    return $translation;
}

1;

{'fraction_non_alphanumeric': 0.16155454862321367, 'fraction_numerical': 0.0020913210177762286, 'mean_word_length': 2.641497461928934, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6974687', 'n_tokens_mistral': 1878, 'n_tokens_neox': 1809, 'n_words': 479}