Serge

 view release on metacpan or  search on metacpan

lib/Serge/Engine.pm  view on Meta::CPAN

    my $source_hash = $self->{src_hash}->{$self->{current_file_rel}};
    die "source_hash is undefined" unless $source_hash ne '';
    # for source language we don't parse translation file, so get_property would return an empty string;
    # DB has a constraint: property value should not be empty. So for the source language we return a dummy non-empty string
    my $source_ts_file_hash = ($lang eq $self->{job}->{source_language}) ? '-' : $self->{db}->get_property("ts:$self->{current_file_id}:$lang");

    my $file_exists = -f $fullpath;
    my $current_mtime = file_mtime($fullpath) if $file_exists;
    my $old_mtime = $self->{db}->get_property("target:mtime:$filekey:$lang");

    # the force flag will be absent if the source file was skipped,
    # so there is no need to check the skip flag here; this optimization will
    # work automatically

    if ($self->{force_flags}->{"$self->{current_file_id}.$lang"} == 0) { # if not forced
        if ($self->{job}->{optimizations}
                and $file_exists
                and ($current_mtime eq $old_mtime)
                and ($source_hash eq $self->{db}->get_property("source:$filekey:$lang"))
                and ($source_ts_file_hash eq $self->{db}->get_property("source:ts:$filekey:$lang"))
            ) {
            print "\t\tSkip generating $fullpath because source file and translations did not change, target file exists and has the same modification time\n" if $self->{debug};
            return;
        }
    }

    my ($src) = $self->read_file($srcpath);

    $result = combine_and(1, $self->run_callbacks('can_generate_localized_file_source', $file, $lang, \$src));
    if ($result eq '0') {
        print "\t\tSkip processing $srcpath because at least one callback returned 0\n" if $self->{debug};
        return;
    }

    $self->run_callbacks('after_load_source_file_for_generating', $srcpath, $lang, \$src);

    $self->clear_disambiguation_cache;

    my $out;
    eval {
        $out = $self->{job}->{parser_object}->parse(\$src, sub { $self->generate_localized_files_for_file_lang_callback(@_) }, $lang);
    };

    if ($@) {
        print "\t\tWARNING: Localized file generation failed; the file will not be saved\n";
        print "\t\tReason: $@\n";
        return undef;
    }

    $result = combine_and(1, $self->run_callbacks('can_save_localized_file', $file, $lang, \$out));
    if ($result eq '0') {
        print "\t\tSkip saving $fullpath because at least one callback returned 0\n";# if $self->{debug};
        return;
    }

    $self->run_callbacks('before_save_localized_file', $file, $lang, \$out);

    my $enc = $self->{job}->{output_encoding};
    my $text;

    # print BOM
    if ($self->{job}->{output_bom}) {
        $text = "\xFF\xFE"         if  (uc($enc) eq 'UTF-16LE');
        $text = "\xFE\xFF"         if ((uc($enc) eq 'UTF-16BE') || (uc($enc) eq 'UTF-16'));
        $text = "\xFF\xFE\x00\x00" if  (uc($enc) eq 'UTF-32LE');
        $text = "\x00\x00\xFE\xFF" if ((uc($enc) eq 'UTF-32BE') || (uc($enc) eq 'UTF-32'));
        $text = "\xEF\xBB\xBF"     if  (uc($enc) eq 'UTF-8');
    }

    # append content
    $text .= encode($enc, $out);

    my $current_hash = generate_hash($text);
    my $old_hash = $self->{db}->get_property("target:$filekey:$lang");

    if ($self->{job}->{optimizations}
            and $file_exists
            and ($current_hash eq $old_hash)
            and ($current_mtime eq $old_mtime)) {
        print "\t\tSkip saving $fullpath: content hash and file modification time are the same\n" if $self->{debug};
    } else {
        my @reasons;

        if (!$self->{job}->{optimizations}) {
            push @reasons, 'forced mode is on';
        } else {
            if (!$file_exists) {
                push @reasons, 'file didn\'t exist before';
            } elsif (!$old_hash) {
                push @reasons, 'file was never saved before';
            } else {
                push @reasons, 'content changed' if $current_hash ne $old_hash;
                push @reasons, 'file was modified on disk' if $current_mtime ne $old_mtime;
            }
        }

        eval { mkpath($dir) };
        die "Couldn't create $dir: $@" if $@;

        # Writing the entire file
        print "\t\tSaving $fullpath, because ".join(', ', @reasons);
        open(OUT, ">$fullpath") || die "Can't write to [$fullpath]: $!";
        binmode(OUT);
        print OUT $text;
        close(OUT);
        my $size = -s $fullpath;
        print " ($size bytes)\n";

        $self->run_callbacks('on_localized_file_change', $file, $lang, \$text);

        $self->{db}->set_property("target:$filekey:$lang", $current_hash);
        $self->{db}->set_property("target:mtime:$filekey:$lang", file_mtime($fullpath)); # read mtime again since the file was saved
    }

    # $source_hash and $source_ts_file_hash might be undefined if the translation file has not been parsed or saved yet before
    # (in e.g. `output_only_mode` where we skip saving any translation files)

    $self->{db}->set_property("source:$filekey:$lang", $source_hash) if $source_hash ne '';
    $self->{db}->set_property("source:ts:$filekey:$lang", $source_ts_file_hash) if $source_ts_file_hash ne '';

    $self->run_callbacks('after_save_localized_file', $file, $lang, \$text);



( run in 1.290 second using v1.01-cache-2.11-cpan-d7f47b0818f )