Get translated count and fuzzy count ... from po file using regex - php

I need some regular expression to split PO (language translation file) file's translated count , fuzzy count and total string count.
I used PHP for the program, I search every where but couldn't found.
please help me.

gettext PO files are so old and ubiquitous, they're a de facto industry standard with great support by a wide variety of tools. Trying to reinvent a solution using regexen here seems very inappropriate when you could be using one of the many PO file parsers instead. For example oscarotero/Gettext:
$translations = Gettext\Extractors\Po::extract('messages.po');
$total = $translated = $fuzzy = 0;
foreach ($translations as $translation) {
$total++;
if (!$translation->hasTranslation()) {
$untranslated++;
}
if (in_array('fuzzy', $translation->getComments())) {
$fuzzy++;
}
}
(Untested, but should work immediately or with slight changes.)
In fact though, there are tools to do this already: Translate Toolkit or Pology, for those I know of:
$ pocount locale/ko/LC_MESSAGES/
data/locale/ko/LC_MESSAGES/messages.po
type strings words (source) words (translation)
translated: 3 ( 0%) 7 ( 0%) 28
fuzzy: 0 ( 0%) 0 ( 0%) n/a
untranslated: 729 ( 99%) 1065 ( 99%) n/a
Total: 732 1072 28
unreviewed: 3 ( 0%) 7 ( 0%) 28
empty: 729 ( 99%) 1065 ( 99%) 0
$ posieve stats locale/ko/
- msg msg/tot w-or w/tot-or w-tr ch-or ch-tr
translated 3 0.4% 15 0.9% 26 93 114
fuzzy 0 0.0% 0 0.0% 0 0 0
untranslated 729 99.6% 1708 99.1% 0 17323 0
total 732 - 1723 - 26 17416 114
obsolete 0 - 0 - 0 0 0

Try this regex,
$total = array();
$translated = array();
$extra ='';
// If fuzzy true then translated count = fuzzy count
if($fuzzy) {
$extra = '#, fuzzy\n';
}
$matched = preg_match_all('/'.$extra.'msgid\s+((?:".*(?<!\\\\)"\s*)+)\s+'.'msgstr\s+((?:".*(?<!\\\\)"\s*)+)/', $po_content, $matches);
for ($i = 0; $i < $matched; $i++) {
if(trim(substr(rtrim($matches[1][$i]), 1, -1))!="") {
$total[] = substr(rtrim($matches[1][$i]), 1, -1);
}
if(trim(substr(rtrim($matches[2][$i]), 1, -1))!="") {
if (strpos(substr(rtrim($matches[2][$i]), 1, -1), 'Language-Team')===false && strpos(substr(rtrim($matches[2][$i]), 1, -1), 'MIME-Version')===false ) {
$translated[] = substr(rtrim($matches[2][$i]), 1, -1);
}
}
}
Total count = count($total);
Translated count = count($translated);

Related

Round up number to highest nearest 9 in laravel

I want to round up a number to highest nearest 9, Here is an example
(12,24,37,75,80)
if i gave this inputs want to get output like below given
(19,29,39,79,89)
I am using PHP(laravel), Please Help Me.
$input = [12,24,37,75,80];
$output = array_map(function($num) {
return (int)($num / 10) * 10 + 9;
}, $input);
I like the simplicity of #HTMHell's answer. And it works perfectly for integers. However, I found, that when using real numbers as input, something like 19.999 will be "rounded up" to 19.
I therefore suggest the following, modified version:
echo json_encode(array_map(function($v){
return ceil(($v+1)/10)*10-1;
},[12,18.99,19.01,24,37,75,80,90]));
// [19,19,29,29,39,79,89,99]
And, to answer #nice_dev's question, 90 should be rounded up to 99.
<?php
$items = array(12,24,37,75,80);
$endDigit = 9; //this should be between 0-9
$newItems = array();
foreach($items as $item){
$final = (int)($item / 10) * 10 + $endDigit;
array_push($newItems,$final);
}
print_r($newItems);
Output
Array ( [0] => 19 [1] => 29 [2] => 39 [3] => 79 [4] => 89 )

Reverting a bitwise/binary number to an array of values?

I have a a list of data that has a value attached to it that constantly gets doubled as it goes up:
0 = value 0
1 = value 1
2 = value 2
4 = value 3
8 = value 4
16 = value 5
32 = value 6
64 = value 7
128 = value 8
256 = value 9
512 = value 10
I have also been given the number x
say x = 76.
Visually, I can see that value 7 (64), value 4 (8), and value 3 (4) all sum up to 76.
What I need to be able to do, is take x, run it through a function, and return an array of the values.
I've tried looping through all the numbers in reverse and taking off what value has been used, but i got confused with lots of if statements.
Is there a built in PHP function to do this? Or am I looking at it the wrong way?
Thanks
May be you are looking for this-
function getArray($x){
$ar = array();
for($i = 0 ; $i < 16; $i++){
if( ($x&(1<<$i)) != 0 ){
array_push($ar, (1<<$i));
// if you need positions; you should use it instead of above line
//array_push($ar, ($i+1));
}
}
return $ar;
}
print_r( getArray(76) );
Output:
Array (
[0] => 4
[1] => 8
[2] => 64
)
The alternate output will be (if you use array_push($ar, ($i+1));)-
Array
(
[0] => 3
[1] => 4
[2] => 7
)
Explanation:
In binary 76 presents 00000000 01001100 in 16 bit. I ran a loop from Least Significant Bit (LSB) to Most Significant Bit (MSB) (0-16). In each loop, I'm generating a new number which contains only i'th bit as 1 and rest of the bits are 0. To generate it I used shifting operator (1 << i) which is actually 2^i. Now I did a bit wise AND operation between x and the new number. If this operation returns any nonzero number that means i'th bit of x is 1 and I'm pushing that position/value inside the array. Finally I'm returning that arry.

Reading array diagonally for transposition cipher?

What I'm doing here is probably stupid and useless, but it turned out to be a great way to learn php, I appreciate your help.
I came up with a cipher which wraps text in a spiral much like Ulam's spiral maps numbers.
Refer to this image:
I consider the whole spiral as a cube, so if the string is too short to form a full cube, the remaining characters are left as empty spaces (in my picture example there is one space left, because the string is 24 characters and the next full cube is at 25 characters.
I want to add a further step of obfuscation, reading the array diagonally, so the output would be like this:
What is an easy/efficient way to achieve this? I'm storing the data in a 2D array, so it looks like this:
field[0][0]='l';
Bonus tangent question: How easily would something like this be deciphered?
Thank you!
This is the schema for a 5x5 square:
yx yx yx yx yx
0 1 2 3 4 a > 00
0 a b c d e b > 10 01
1 b c d e f c > 20 11 02
2 c d e f g d > 30 21 12 03
3 d e f g h e > 40 31 22 13 04
4 e f g h i f > 41 32 23 14
g > 42 33 24
h > 43 34
i > 44
As you can see, we have:
9 groups (= cols+rows-1 or keys+keys+1);
in each line, the y+x sum is the same, increasing from 0 to 8;
in each line, the y decreases, while the x increases.
each line ends when x reaches initial y
Based on these assumptions, we can write a single loop, using $sum and $startY as criteria to change line: when the decreasing $x has same value of $startY, we increment $sum and we set next $startY to the lowest value between $sum and the higher $array key, then we set next $x to the difference between $sum and $y:
$sum = $startY = $y = $x = 0;
while( $sum < 2*count($array)-1 )
{
echo $array[$y][$x];
if( $x == $startY )
{
$sum++;
$startY = $y = min( $sum, count($array)-1 );
$x = $sum - $y;
}
else
{
$y--;
$x++;
}
}
The result for above square is:
abbcccddddeeeeeffffggghhi
Looking at this eval.in demo you can see three different examples.
Just use for loops. It doesn't matter what language you are learning, you need to learn how to use for loops (or while loops or foreach loops or any good control structure).
You are going 00, then 10, 01, then 20, 11, 02, then 30, 21, 12, 03, etc... YOu can see that the first number decreases by 1 and the second number increases by 1. That goes until you hit n0...0n. That covers the first half of the square...
// Assume $n is the width/height of the square
for($m=0; $m<=$n; $m++)
{
for($a=$n; $a>=0; $a--)
{
for($b=0; $b<=$n; $b++)
{
//Do whatever you want with $array[$a][$n]...
}
}
}
Now, the second half of the square hits 41, 32, 23, 14 on the first stripe. It hits 42, 33, 24 on the second stripe. It hits 43, 34, and finally 44. You can see they both step up until they hit $n
for($m=1; $m<=$n; $m++)
{
for($b=$m; $b<=$n; $b++) // Put B on the outside because it is the limitation
{
for($a=4; $b<=$n; $a--)
{
//Do what you want with $a and $b
}
}
}
Now... can this be deciphered easily? Yes. You are just scrambling up the letters. No matter how you scramble it, it is deciphered easily. You need to substitute the letters with a replacement set that changes. Optimally, you want a completely new replacement set per letter you replace - which is difficult to use. So, most ciphers use a set of replacement sets, say 32 sets of replacement letters or symbols, that cycle through as randomly as possible.

PHP auto convert price to 99 rather than 100

I have different prices:
100
550
799
1200
350
Wonder how i can automatically convert them to
99
549
799
1200
349
I'd just do -1, but some are already correct like 799, and i don't want it to be 798.
Cant think of way to do this conversion i am good with PHP but not great with math. I bet we need to find if it divides by 2 if yes then subtract 1 if not then do nothing.
if ($price % 2) {
$price = intval($price) - 1;
}
Is this the best way to do it?
You could do something like this :
if (($price % 50) == 0)
{
$price--;
}
Everytime the modulo of 50 will be equal to zero (this will be the case for any number that ends with "50" or "100"), it will remove one.
Change the second value (50 in this case) if you want to target more or less prices.
Something like this?
if(($price % 10) == 0) {
$price--;
}
As you don't want to have 798, your code does not work
But you can use this.
if ($price % 10) {
$price = intval($price) - 1;
}
799 % 2 = 1
800 % 2 = 0
798 % 2 = 0
799 % 10 = 0
800 % 10 = 1
798 % 10 = 0
or %50 if you only want to subtract 1 from numbers like 750 and 800

php format input data and put it into multiple arrays

i'm trying to put input (below) into multiple arrays (or maybe its simpler into one array) to finally export it into mysql table, input data goes like:
0 98
77 09
0 12
0 98234
32 0
0 1
0 0
345 32
34 9
6437 34
789 0
0 0
.
.
34 0
my simple code ($run_txt_filter1 is input):
if ( $counted == 64)
{
echo "line's number: ".$counted;
//echo $run_txt_filter1;
for ($modi = 0; $modi <= 15; $modi++)
{
for ($simhi = 1; $simhi <= 4 ; $simhi++)
{
$exploded=explode(" ", $run_txt_filter1);
var_dump($exploded)." \n";
}
}
}
Why var_dump keeps saying the id from 0-64 ? (there always should be 64 input lines).
What a really want to achieve is:
array0=(0, 77, 0, 0)
array1=(98, 09, 12, 98234)
array2=(32, 0, 0, 345)
.
.
array30=(0, 12, 0, 34)
array31=(0, 0, 0, 0)
thanks in advance
try to separate your explode for the next line and explode for the white space. cause on your code above it's reading the whole string as one causing your program to store it on a single array. so it would be a nested loop by then. :)
Considering this input:
$in = <<<IN
0 98
77 09
0 12
0 98234
32 0
0 1
0 0
345 32
34 9
6437 34
789 0
0 0
IN;
This algorithm solves your problem i think:
$final_array = array();
$offset = 0;
foreach(preg_split("/(\r?\n){2,}/",$in) as $block){
foreach(preg_split("/(\r?\n)/",$block) as $line){
foreach(preg_split("/\s+/",$line) as $column => $value){
if($value=='') continue;
if(!isset($final_array[$offset+$column]))
$final_array[$offset+$column] = array();
$final_array[$offset+$column][]=$value;
}
}
$offset = count($final_array);
}
print_r($final_array);
try something similar to this one I'm not sure if this would work:
inputs:
$inputs = "0 98
77 09
0 12
0 98234
32 0
0 1
0 0
345 32
34 9
6437 34
789 0
0 0
.
.
34 0";
code:
$run_txt_filter1 = explode("\n", $inputs);
if(count($run_txt_filter1) == 64)
{
foreach($run_txt_filter1 as $input)
{
$exploded = explode(' ', $input);
print_r($exploded);
}
}
The "\n" is the next line for windows but it's different on linux its "\r" I'm not sure if it would work you may also try the combination as
explode("\r\n", $inputs);
but just a try if the next line won't work I think you could use some other way to separate each set of values either user other type of characters like ',',';',':' etc. :)

Categories