Compare commits

...

27 Commits

Author SHA1 Message Date
zzz
65514da874 bump -1 2024-07-25 09:34:32 -04:00
zzz
86248df17b remove unused rrd4j class 2024-07-25 09:33:46 -04:00
zzz
5ee65a30f8 Util: Add new processors for CPUID 2024-07-25 09:19:39 -04:00
zzz
b39741bf52 imagegen: Convert identicons to SVG
to reduce memory usage
2024-07-25 09:16:13 -04:00
zzz
bfb5557099 i2ptunnel: Additional fixes for invalid entries in filter file (Gitlab #483)
as reported by drzed
2024-07-25 08:59:36 -04:00
zzz
6b6335cef4 checklist update 2024-07-25 08:49:39 -04:00
zzz
bdf9d67a06 Console: Enable compression of js and svg files
and lower size threshold, now that we have some larger js/svg resources
2024-07-25 08:47:16 -04:00
zzz
07b64ac7d6 Installer: Fix some izpack5 translated languages
Copy out of izpack5 and rename resources to be loaded at build time:
- bra -> por
- chn -> zho
- idn -> ind

See installer5.xml for notes on why.

Also restore Persian translation, was removed in transition from izpack 4 to 5,
will only be shown if the locale is in the JVM, otherwise will generate warning at runtime.
2024-07-25 08:42:35 -04:00
zzz
73cae644e5 Build: Fix rrd4j dependency, other cleanups 2024-07-25 08:18:52 -04:00
zzz
6aa6dad5be rrd4j: More optimizations for graph generation 2024-07-25 08:08:24 -04:00
zzz
541e456809 Increase max concurrent graphs generation 2024-07-25 08:05:34 -04:00
zzz
f84963bf06 Javadoc for new svg package 2024-07-25 08:02:11 -04:00
zzz
a8df1402d9 Merge branch 'svg-graphs' into 'master'
Convert graphs to SVG

See merge request i2p-hackers/i2p.i2p!208
2024-07-25 11:52:07 +00:00
zzz
3cc1eb7cc3 Convert graphs to SVG 2024-07-25 11:52:07 +00:00
zzz
23f267b67b Console: Add link to translation status report 2024-07-25 07:39:35 -04:00
zzz
cd02d9f088 Merge branch 'txreport' into 'master'
Console: Add translation status report

See merge request i2p-hackers/i2p.i2p!207
2024-07-25 11:35:36 +00:00
zzz
1b80039619 Console: Add translation status report 2024-07-25 11:35:36 +00:00
6601e56281 I2Tunnel: fix CSS error 2024-07-24 13:12:13 -04:00
3f2cee1f2c Debian: update changelogs 2024-07-20 13:42:06 -04:00
94248d2019 CI: sleep longer between attempts to ping a mirror 2024-07-19 19:13:55 -04:00
63326dc48b Router: Bump version for release 2024-07-19 11:51:48 -04:00
2de39dd445 Tests: Replace keys in SU3FileSpec.scala with new keys 2024-07-19 11:14:19 -04:00
8212f79bc0 remove old key 2024-07-19 05:06:24 -04:00
b97fd8ee04 check in missing file 2024-07-19 05:05:41 -04:00
728cbfccb1 Tests: fix CertUtilSpec.java 2024-07-18 21:25:59 -04:00
ae1939aafc Merge branch 'master' of i2pgit.org:i2p-hackers/i2p.i2p 2024-07-18 19:11:36 -04:00
ce5b1f04b8 Unit Tests: update i2pseeds.su3 file used in unit tests 2024-07-18 19:11:01 -04:00
44 changed files with 2600 additions and 283 deletions

View File

@ -15,8 +15,9 @@ jobs:
changelog.txt
- name: download release artifacts
run: |
sudo apt-get install wget ca-certificates gpg sed curl
while true; do wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe && break; done
sudo apt-get install wget ca-certificates gpg sed curl git
git pull --tags
while true; do sleep 60m; wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe && break; done
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')-signed.exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').jar

View File

@ -33,9 +33,14 @@ abstract class FilterDefinitionElement {
* Utility method to create a Hash object from a .b32 string
*/
protected static Hash fromBase32(String b32) throws InvalidDefinitionException {
if (b32.length() != 60)
throw new InvalidDefinitionException("Invalid b32 " + b32);
if (!b32.endsWith(".b32.i2p"))
throw new InvalidDefinitionException("Invalid b32 " + b32);
b32 = b32.substring(0, b32.length() - 8);
return new Hash(Base32.decode(b32));
String s = b32.substring(0, 52);
byte[] b = Base32.decode(s);
if (b == null)
throw new InvalidDefinitionException("Invalid b32 " + b32);
return Hash.create(b);
}
}

View File

@ -153,7 +153,7 @@ public class NineBlockIdenticonRenderer2 implements IdenticonRenderer {
}
public BufferedImage render(BigInteger code, int size) {
return renderQuilt(code.intValue(), size);
return renderQuilt(null, code.intValue(), size);
}
/**
@ -172,10 +172,22 @@ public class NineBlockIdenticonRenderer2 implements IdenticonRenderer {
* @return identicon image
*/
public BufferedImage render(int code, int size) {
return renderQuilt(code, size);
return renderQuilt(null, code, size);
}
protected BufferedImage renderQuilt(int code, int size) {
/**
* @param g custom Graphics2D or null
* @since 0.9.64
*/
public BufferedImage render(Graphics2D g, int code, int size) {
return renderQuilt(g, code, size);
}
/**
* @param gg custom Graphics2D or null
* @since 0.9.64
*/
protected BufferedImage renderQuilt(Graphics2D gg, int code, int size) {
// -------------------------------------------------
// PREPARE
//
@ -220,9 +232,15 @@ public class NineBlockIdenticonRenderer2 implements IdenticonRenderer {
// RENDER
//
BufferedImage targetImage = new BufferedImage(size, size,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = targetImage.createGraphics();
BufferedImage targetImage = null;
Graphics2D g;
if (gg != null) {
g = gg;
} else {
targetImage = new BufferedImage(size, size,
BufferedImage.TYPE_INT_RGB);
g = targetImage.createGraphics();
}
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
@ -256,7 +274,8 @@ public class NineBlockIdenticonRenderer2 implements IdenticonRenderer {
drawPatch(g, 0, blockSize2, blockSize, cornerType, cornerTurn++,
cornerInvert, fillColor, strokeColor);
g.dispose();
if (gg == null)
g.dispose();
return targetImage;
}

View File

@ -8,6 +8,7 @@
<pathelement location="../identicon/build/identicon.jar" />
<pathelement location="../zxing/build/zxing.jar" />
<pathelement location="../../../build/i2p.jar" />
<pathelement location="../../../build/jrobin.jar" />
</path>
<target name="all" depends="war" />

View File

@ -19,6 +19,7 @@ import com.docuverse.identicon.NineBlockIdenticonRenderer2;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.rrd4j.SimpleSVGGraphics2D;
import net.i2p.util.ConvertToHash;
import net.i2p.util.Log;
@ -67,10 +68,10 @@ public class IdenticonServlet extends HttpServlet {
private static final String PARAM_IDENTICON_SIZE_SHORT = "s";
private static final String PARAM_IDENTICON_CODE_SHORT = "c";
private static final String IDENTICON_IMAGE_FORMAT = "PNG";
private static final String IDENTICON_IMAGE_MIMETYPE = "image/png";
private static final String IDENTICON_IMAGE_MIMETYPE = "image/svg+xml";
private static final long DEFAULT_IDENTICON_EXPIRES_IN_MILLIS = 24 * 60 * 60 * 1000;
private int version = 1;
private final IdenticonRenderer renderer = new NineBlockIdenticonRenderer2();
private final NineBlockIdenticonRenderer2 renderer = new NineBlockIdenticonRenderer2();
private IdenticonCache cache;
private long identiconExpiresInMillis = DEFAULT_IDENTICON_EXPIRES_IN_MILLIS;
@ -147,6 +148,7 @@ public class IdenticonServlet extends HttpServlet {
// retrieve image bytes from either cache or renderer
if (cache == null
|| (imageBytes = cache.get(identiconETag)) == null) {
/*
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
RenderedImage image;
try {
@ -160,6 +162,20 @@ public class IdenticonServlet extends HttpServlet {
}
ImageIO.write(image, IDENTICON_IMAGE_FORMAT, byteOut);
imageBytes = byteOut.toByteArray();
*/
SimpleSVGGraphics2D g = new SimpleSVGGraphics2D(size, size);
try {
renderer.render(g, code, size);
} catch (Throwable t) {
// java.lang.NoClassDefFoundError: Could not initialize class java.awt.GraphicsEnvironment$LocalGE
Log log = I2PAppContext.getGlobalContext().logManager().getLog(IdenticonServlet.class);
//log.logAlways(Log.WARN, "Identicon render failure: " + t);
log.error("Identicon render failure", t);
response.setStatus(403);
return;
}
String s = g.getSVG();
imageBytes = s.getBytes("UTF-8");
if (cache != null)
cache.add(identiconETag, imageBytes);
} else {
@ -178,6 +194,7 @@ public class IdenticonServlet extends HttpServlet {
// return image bytes to requester
response.setContentType(IDENTICON_IMAGE_MIMETYPE);
response.setCharacterEncoding("UTF-8");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Accept-Ranges", "none");
response.setContentLength(imageBytes.length);

View File

@ -37,6 +37,9 @@
encoding="UTF-8"
includes="**/*.java" >
<compilerarg line="${javac.compilerargs}" />
<classpath>
<pathelement location="../../../core/java/build/i2p.jar" />
</classpath>
</javac>
</target>

View File

@ -0,0 +1,431 @@
package net.i2p.rrd4j;
import java.text.AttributedCharacterIterator;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import static java.awt.geom.PathIterator.*;
import java.awt.image.*;
import java.awt.image.renderable.RenderableImage;
/**
* Very simple SVGGraphics2D, only enough for basic rrd4j use, without dependencies.
* Plus a few things that rrd4j doesn't use, but not much.
* Unsupported things will throw UnsupportedOperationExceptions.
*
* Supports custom RenderingHints for id and class on top-level svg element.
* Supports custom RenderingHints for id, class, title, and arbitrary attributes
* on all drawn elements.
* Supports custom RenderingHints for inner SVG on all drawn elements except text.
*
* No standard Java AWT hints are supported.
* Antialiasing is done automatically.
* Antialiasing hints have no effect.
*
* License: Apache 2.0 (same as rrd4j)
*
* @since 0.9.64
* @author zzz
*/
public class SimpleSVGGraphics2D extends Graphics2D {
//// hints - all strings except for ATTMAP ////
/**
* On the top svg element.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_SVG_ID = new RHKey(1);
/**
* On the top svg element.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_SVG_CLASS = new RHKey(2);
/**
* On the top svg element.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_SVG_TITLE = new RHKey(3);
/**
* On the next element drawn, one-shot, will be removed after rendering.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_ELEMENT_ID = new RHKey(4);
/**
* On the next element drawn, one-shot, will be removed after rendering.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_ELEMENT_CLASS = new RHKey(5);
/**
* Value is a Map of String to String of extra attributes on the next element drawn, one-shot, will be removed after rendering.
* Map keys must be XML-escaped by caller if necessary.
* Map values will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_ELEMENT_ATTMAP = new RHKey(6);
/**
* On the next element drawn, one-shot, will be removed after rendering.
* Value is a string and will be XML-escaped when rendering.
*/
public static final RenderingHints.Key KEY_ELEMENT_TITLE = new RHKey(7);
/**
* Put "inside" the next element drawn, one-shot, will be removed after rendering.
* Value is an XML string and must be XML-escaped by caller if necessary.
*/
public static final RenderingHints.Key KEY_ELEMENT_INNERSVG = new RHKey(8);
private final StringBuilder buf;
private final SimpleSVGMaker svg;
private final Map<Object,Object> hints = new HashMap<Object,Object>();
private AffineTransform transform = new AffineTransform();
private final FontRenderContext frctx = new FontRenderContext(transform, true, true);
private final int width, height;
private final Rectangle origclip;
// null unless different from origclip
private Rectangle clip;
private String clipID;
private Color bgcolor = Color.WHITE;
private Paint paint = Color.BLACK;
private Stroke stroke = new BasicStroke(1);
private Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
private boolean started;
public SimpleSVGGraphics2D(int width, int height) {
this.width = width;
this.height = height;
origclip = new Rectangle(0, 0, width, height);
buf = new StringBuilder(16*1024);
svg = new SimpleSVGMaker(buf);
}
public String getSVG() {
stop();
String rv = buf.toString();
dispose();
return rv;
}
private void start() {
if (!started) {
String id = (String) hints.remove(KEY_SVG_ID);
String cl = (String) hints.remove(KEY_SVG_CLASS);
svg.startSVG(width, height, bgcolor, id, cl);
started = true;
}
}
private void stop() {
if (started) {
if (!transform.isIdentity()) {
svg.endGroup();
transform = frctx.getTransform();
}
svg.endSVG();
clip = null;
clipID = null;
started = false;
}
}
public void dispose() { buf.setLength(0); }
//// API bypass ////
/**
* Graphics2D API bypass, advanced use only
*/
public SimpleSVGMaker getMaker() { start(); return svg; }
/**
* Graphics2D API bypass, advanced use only
*/
public void append(String s) { start(); buf.append(s).append('\n'); }
//// draws/fills used by rrd4j ////
public void drawLine(int x1, int y1, int x2, int y2) {
start();
svg.drawLine(x1, y1, x2, y2, (Color) paint, (BasicStroke) stroke, clipID, hints);
}
public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
start();
svg.drawPolyline(xPoints, yPoints, nPoints, (Color) paint, (BasicStroke) stroke, clipID, hints);
}
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
start();
String id = (String) hints.remove(KEY_ELEMENT_ID);
String cl = (String) hints.remove(KEY_ELEMENT_CLASS);
svg.fillPolygon(xPoints, yPoints, nPoints, (Color) paint, clipID, hints);
}
public void fillRect(int x, int y, int width, int height) {
if (!started) {
// rrd4j calls this first with the background color, it does not call setBackground()
if (x == 0 && y == 0 && width == this.width && height == this.height) {
// disable setting the background color, this is it
bgcolor = null;
}
start();
}
svg.drawRect(x, y, width, height, null, (Color) paint, null, clipID, hints);
}
//// text ////
public void drawString(String str, int x, int y) {
start();
svg.drawText(str, x, y, (Color) paint, font, clipID, hints);
}
public void drawString(String str, float x, float y) { drawString(str, (int) x, (int) y); }
public FontRenderContext getFontRenderContext() { return frctx; }
//// supported things not used by rrd4j ////
/**
* Circles only for now, must be width == height and arcAngle == 360
* Otherwise throws UnsupportedOperationException
* TODO
*/
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
if (width != height || arcAngle != 360)
throw new UnsupportedOperationException("circles only!");
start();
int r = width / 2;
svg.drawCircle(x + r, y + r, r, (Color) paint, null, (BasicStroke) stroke, clipID, hints);
}
/**
* Circles only for now, must be width == height and arcAngle == 360
* Otherwise throws UnsupportedOperationException
* TODO
*/
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
if (width != height || arcAngle != 360)
throw new UnsupportedOperationException("circles only!");
start();
int r = width / 2;
svg.drawCircle(x + r, y + r, r, null, (Color) paint, (BasicStroke) stroke, clipID, hints);
}
public void clearRect(int x, int y, int width, int height) {
boolean wasStarted = started;
if (!wasStarted) {
start();
} else {
// don't do it twice at the start
String id = (String) hints.remove(KEY_ELEMENT_ID);
String cl = (String) hints.remove(KEY_ELEMENT_CLASS);
svg.drawRect(x, y, width, height, null, bgcolor, null, clipID, hints);
}
}
public void draw(Shape s) {
drawOrFill(s, true, false);
}
public void fill(Shape s) {
drawOrFill(s, false, true);
}
/**
* Lines only for now
* Will draw a closed shape, open shapes will become closed.
* Arcs will throw UnsupportedOperationException
*/
private void drawOrFill(Shape s, boolean draw, boolean fill) {
int[] x = new int[16];
int[] y = new int[16];
int i = 0;
float[] coords = new float[6];
for (PathIterator it = s.getPathIterator(frctx.getTransform()); !it.isDone(); it.next()) {
int type = it.currentSegment(coords);
switch(type) {
case SEG_MOVETO:
case SEG_LINETO:
if (i >= x.length) {
x = Arrays.copyOf(x, x.length * 2);
y = Arrays.copyOf(y, y.length * 2);
}
x[i] = (int) coords[0];
y[i++] = (int) coords[1];
break;
case SEG_CLOSE:
break;
case SEG_CUBICTO:
case SEG_QUADTO:
throw new UnsupportedOperationException("Unsupported curved shape");
default:
throw new UnsupportedOperationException("Unsupported type " + type);
}
}
if (draw)
drawPolyline(x, y, i);
else
fillPolygon(x, y, i);
}
//// clips ////
public void setClip(int x, int y, int width, int height) {
setClip(new Rectangle(x, y, width, height));
}
public void setClip(Shape clip) {
if (clip.equals(this.clip))
return;
if (this.clip == null && clip.equals(origclip))
return;
Rectangle newclip;
if (clip instanceof Rectangle)
newclip = (Rectangle) clip;
else
newclip = clip.getBounds();
if (clip.equals(origclip)) {
this.clip = null;
clipID = null;
return;
}
// define new clip, save the Rectangle and ID
clipID = svg.defineClipPath(newclip);
this.clip = newclip;
}
//// transforms ////
public void translate(int x, int y) { translate((double) x, (double) y); }
public void translate(double tx, double ty) {
AffineTransform ntx = (AffineTransform) transform.clone();
ntx.translate(tx, ty);
setTransform(ntx);
}
public void rotate(double theta) {
AffineTransform ntx = (AffineTransform) transform.clone();
ntx.rotate(theta);
setTransform(ntx);
}
public void rotate(double theta, double x, double y) {
AffineTransform ntx = (AffineTransform) transform.clone();
ntx.rotate(theta, x, y);
setTransform(ntx);
}
public void scale(double sx, double sy) {
AffineTransform ntx = (AffineTransform) transform.clone();
ntx.scale(sx, sy);
setTransform(ntx);
}
public void shear(double shx, double shy) {
AffineTransform ntx = (AffineTransform) transform.clone();
ntx.shear(shx, shy);
setTransform(ntx);
}
public void setTransform(AffineTransform tx) {
// For each transform, we close the previous group if non-identity,
// and start a new group with a transform containing the new combined transform.
// We don't 'stack' groups with each individual transform.
if (transform.equals(tx))
return;
if (!transform.isIdentity())
svg.endGroup();
if (!tx.isIdentity()) {
String matrix = String.format(Locale.US, "matrix(%.3f %.3f %.3f %.3f %.3f %.3f)",
tx.getScaleX(), tx.getShearY(),
tx.getShearX(), tx.getScaleY(),
tx.getTranslateX(), tx.getTranslateY());
svg.startGroup(null, null, "transform", matrix);
}
transform = tx;
}
public AffineTransform getTransform() { return transform; }
//// setters ////
public void setFont(Font font) { this.font = font; }
public void setPaint(Paint paint) { this.paint = paint; }
public void setStroke(Stroke stroke) { this.stroke = stroke; }
//// we support these but unused by rrd4j ////
public void setBackground(Color color) { bgcolor = color; }
public Color getBackground() { return bgcolor; }
public Shape getClip() { return clip; }
public Rectangle getClipBounds() { return clip; }
public void setColor(Color color) { paint = color; }
public Color getColor() { return (Color) paint; }
public Font getFont() { return font; }
public Paint getPaint() { return paint; }
public Stroke getStroke() { return stroke; }
//// Hints ////
private static class RHKey extends RenderingHints.Key {
public RHKey(int k) {
super(k);
}
public boolean isCompatibleValue(Object o) {
if (intKey() == 6)
return o instanceof Map;
return o instanceof String;
}
}
public void addRenderingHints(Map<?,?> hints) { this.hints.putAll(hints); }
public Object getRenderingHint(RenderingHints.Key hintKey) { return hints.get(hintKey); }
public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { hints.put(hintKey, hintValue); }
public void setRenderingHints(Map<?,?> hints) { this.hints.clear(); addRenderingHints(hints); }
//// unsupported things ////
//// all do nothing or throw ////
public void clipRect(int x, int y, int width, int height) { throw new UnsupportedOperationException(); }
public void clip(Shape s) { throw new UnsupportedOperationException(); }
public void copyArea(int x, int y, int width, int height, int dx, int dy) { throw new UnsupportedOperationException(); }
public Graphics create() { throw new UnsupportedOperationException(); }
public void drawGlyphVector(GlyphVector g, float x, float y) { throw new UnsupportedOperationException(); }
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int x, int y, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver obs) { throw new UnsupportedOperationException(); }
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver obs) { throw new UnsupportedOperationException(); }
public void drawOval(int x, int y, int width, int height) { throw new UnsupportedOperationException(); }
public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { throw new UnsupportedOperationException(); }
public void drawRenderableImage(RenderableImage img, AffineTransform xform) { throw new UnsupportedOperationException(); }
public void drawRenderedImage(RenderedImage img, AffineTransform xform) { throw new UnsupportedOperationException(); }
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { throw new UnsupportedOperationException(); }
public void drawString(AttributedCharacterIterator iterator, float x, float y) { throw new UnsupportedOperationException(); }
public void drawString(AttributedCharacterIterator iterator, int x, int y) { throw new UnsupportedOperationException(); }
public void fillOval(int x, int y, int width, int height) { throw new UnsupportedOperationException(); }
public void fillPolyline(int[] xPoints, int[] yPoints, int nPoints) { throw new UnsupportedOperationException(); }
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { throw new UnsupportedOperationException(); }
public Composite getComposite() { return null; }
public GraphicsConfiguration getDeviceConfiguration() { return null; }
public FontMetrics getFontMetrics(Font f) { return null; }
public RenderingHints getRenderingHints() { return null; }
public boolean hit(Rectangle rect, Shape s, boolean onStroke) { return false; }
public void setComposite(Composite comp) { throw new UnsupportedOperationException(); }
public void setPaintMode() {}
public void setXORMode(Color color) { throw new UnsupportedOperationException(); }
public void transform(AffineTransform tx) {}
}

View File

@ -0,0 +1,75 @@
package net.i2p.rrd4j;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import java.io.OutputStream;
import org.rrd4j.graph.ImageWorker;
/**
* rrd4j adapter for SimpleSVGGraphics2D
*
* Requires: rrd4j 3.10 or higher
* Ref: https://github.com/rrd4j/rrd4j/issues/165
*
* Usage:
* No ImageIO/BufferedImage/ImageWriter required!
*
*<pre>
* RRDGraph graph = new RrdGraph(graphdef, new SimpleSVGImageWorker(width, height));
* outputstream.write(graph.getRrdGraphInfo().getBytes());
*</pre>
*
* License: Apache 2.0 (same as rrd4j)
*
* @since 0.9.64
* @author zzz
*/
public class SimpleSVGImageWorker extends ImageWorker {
private SimpleSVGGraphics2D g2d;
private AffineTransform initialAffineTransform;
private int imgWidth;
private int imgHeight;
public SimpleSVGImageWorker(int width, int height) {
resize(width, height);
}
protected void resize(int width, int height) {
imgWidth = width;
imgHeight = height;
g2d = new SimpleSVGGraphics2D(imgWidth, imgHeight);
initialAffineTransform = g2d.getTransform();
setG2d(g2d);
}
protected void reset(Graphics2D g2d) {
g2d.setTransform(initialAffineTransform);
g2d.setClip(0, 0, imgWidth, imgHeight);
}
protected void makeImage(OutputStream os) throws IOException {
os.write(g2d.getSVG().getBytes("UTF-8"));
}
/**
* Overridden because the SVG format essentially strips leading/trailing spaces,
* causing alignment issues in ValueAxis with the %x.y number formatting.
* Consecutive spaces within text are also probably collapsed, that is not addressed here.
*/
@Override
protected void drawString(String text, int x, int y, Font font, Paint paint) {
super.drawString(text.trim(), x, y, font, paint);
}
/**
* Overridden because the SVG format essentially strips leading/trailing spaces,
* causing alignment issues in ValueAxis with the %x.y number formatting.
* Consecutive spaces within text are also probably collapsed, that is not addressed here.
*/
@Override
protected double getStringWidth(String text, Font font) {
return super.getStringWidth(text.trim(), font);
}
}

View File

@ -0,0 +1,446 @@
package net.i2p.rrd4j;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle;
import net.i2p.data.DataHelper;
import static net.i2p.rrd4j.SimpleSVGGraphics2D.*;
/**
* Create full or partial SVG images, without dependencies.
* Does not extend or use Graphics2D or ImageWriter.
*
* Each drawn element can be passed an optional CSS ID and/or classes,
* for easy styling and manipulation via CSS or js.
* All parameters are set as attributes, not as inline style,
* so a separate CSS style may easily override them.
* If inline style is desired, add it with the KEY_ELEMENT_ATTMAP hint.
*
* Unlike in Graphics2D, the border and fill for an object may be drawn in
* the same call, with separate colors.
*
* There is no state here other than the StringBuffer;
* there is no concept of current Color or Stroke or Font;
* caller must keep track of current Colors, Stroke, and Font, and pass them in
* on every draw() call, and/or overridden via CSS.
*
* License: Apache 2.0 (same as rrd4j)
*
* @since 0.9.64
* @author zzz
*/
public class SimpleSVGMaker {
private final StringBuilder buf;
private int clipid;
public SimpleSVGMaker(StringBuilder buf) {
this.buf = buf;
}
/**
* Start svg tag
* @param bgcolor null for none
* @param id CSS id or null for none
* @param clz CSS class or null for none
*/
public void startSVG(int width, int height, Color bgcolor, String id, String clz) {
buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
// "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" +
"<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
addIDClass(id, clz);
addString("viewBox", "0 0 " + width + ' ' + height);
addInt("width", width);
addInt("height", height);
buf.append(">\n");
if (bgcolor != null && bgcolor.getAlpha() > 0)
drawRect(0, 0, width, height, null, bgcolor, null, null, Collections.emptyMap());
}
/**
* End svg tag
*/
public void endSVG() {
buf.append("</svg>\n");
}
/**
* Start group
* @param id CSS id or null for none
* @param clz CSS class or null for none
* @param att an attribute to add att=val, e.g. "transform", or null for none
* @param val an attribute to add att=val, or null for none
*/
public void startGroup(String id, String clz, String att, String val) {
buf.append("<g ");
addIDClass(id, clz);
if (att != null && val != null)
addString(att, val);
buf.append(">\n");
}
/**
* End group
*/
public void endGroup() {
buf.append("</g>\n");
}
/**
* Define clip path
* @return a unique ID to pass to draw() calls
*/
public String defineClipPath(Rectangle clip) {
buf.append("<clipPath ");
String rv = "clip-" + hashCode() + '-' + (clipid++);
addIDClass(rv, null);
buf.append("><rect ");
addInt("x", (int) clip.getX());
addInt("y", (int) clip.getY());
addInt("width", (int) clip.getWidth());
addInt("height", (int) clip.getHeight());
buf.append("/></clipPath>\n");
return rv;
}
/**
* Draw circle centered on x,y with a radius given
* @param border null for none
* @param fill null for none
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void drawCircle(int x, int y, int radius, Color border, Color fill, BasicStroke stroke, String clipid, Map<Object, Object> hints) {
buf.append("<circle ");
addAttributes(hints);
addClipPath(clipid);
addInt("cx", x);
addInt("cy", y);
addInt("r", radius);
addStroke("fill", fill, null);
addStroke("stroke", border, stroke);
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
String inner = (String) hints.remove(KEY_ELEMENT_INNERSVG);
if (title != null || inner != null) {
buf.append(">\n");
addInner(title, inner);
buf.append("</circle>\n");
} else {
buf.append("/>\n");
}
}
/**
* Draw square centered on x,y with a width/height given
* @param border null for none
* @param fill null for none
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void drawSquare(int x, int y, int sz, Color border, Color fill, BasicStroke stroke, String clipid, Map<Object, Object> hints) {
drawRect(x - (sz/2), y - (sz/2), sz, sz, border, fill, stroke, clipid, hints);
}
/**
* Draw rect
* @param border null for none
* @param fill null for none
* @param hints non-null
*/
public void drawRect(int x, int y, int width, int height, Color border, Color fill, BasicStroke stroke, String clipid, Map<Object, Object> hints) {
buf.append("<rect ");
addAttributes(hints);
addClipPath(clipid);
addInt("x", x);
addInt("y", y);
addInt("width", width);
addInt("height", height);
addStroke("fill", fill, null);
addStroke("stroke", border, stroke);
buf.append("shape-rendering=\"crispEdges\" ");
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
String inner = (String) hints.remove(KEY_ELEMENT_INNERSVG);
if (title != null || inner != null) {
buf.append(">\n");
addInner(title, inner);
buf.append("</rect>\n");
} else {
buf.append("/>\n");
}
}
/**
* Draw line
* @param color null to let CSS do it
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void drawLine(int x1, int y1, int x2, int y2, Color color, BasicStroke stroke, String clipid, Map<Object, Object> hints) {
buf.append("<line ");
addAttributes(hints);
addClipPath(clipid);
addInt("x1", x1);
addInt("y1", y1);
addInt("x2", x2);
addInt("y2", y2);
addStroke("stroke", color, stroke);
// don't do this for diagonal lines, it kills antialiasing
if (x1 == x2 || y1 == y2)
buf.append("shape-rendering=\"crispEdges\" ");
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
String inner = (String) hints.remove(KEY_ELEMENT_INNERSVG);
if (title != null || inner != null) {
buf.append(">\n");
addInner(title, inner);
buf.append("</line>\n");
} else {
buf.append("/>\n");
}
}
/**
* Draw polyline
* @param color null to let CSS do it
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void drawPolyline(int[] x, int[] y, int sz, Color color, BasicStroke stroke, String clipid, Map<Object, Object> hints) {
if (sz < 2)
return;
buf.append("<path ");
addAttributes(hints);
addClipPath(clipid);
buf.append("d=\"M");
buf.append(x[0]).append(',').append(y[0]);
for (int i = 1; i < sz; i++) {
// use relative coords to save a little space
buf.append('l');
buf.append(x[i] - x[i-1]).append(',').append(y[i] - y[i-1]);
}
buf.append("\" ");
addStroke("stroke", color, stroke);
buf.append("fill=\"none\" ");
// this is good for the horizontal/vertical paths drawn by rrd4j,
// but not so great for diagonal path segments
// Take our cue from the first segment
if (x[0] == x[1] || y[0] == y[1])
buf.append("shape-rendering=\"crispEdges\" ");
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
String inner = (String) hints.remove(KEY_ELEMENT_INNERSVG);
if (title != null || inner != null) {
buf.append(">\n");
addInner(title, inner);
buf.append("</path>\n");
} else {
buf.append("/>\n");
}
}
/**
* Fill polygon
* @param color null to let CSS do it
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void fillPolygon(int[] x, int[] y, int sz, Color color, String clipid, Map<Object, Object> hints) {
if (sz < 2)
return;
buf.append("<path ");
addAttributes(hints);
addClipPath(clipid);
buf.append("d=\"M");
buf.append(x[0]).append(',').append(y[0]);
for (int i = 1; i < sz; i++) {
// use relative coords to save a little space
buf.append('l');
buf.append(x[i] - x[i-1]).append(',').append(y[i] - y[i-1]);
}
buf.append("Z\" ");
addStroke("fill", color, null);
buf.append("stroke=\"none\" ");
// see above
if (x[0] == x[1] || y[0] == y[1])
buf.append("shape-rendering=\"crispEdges\" ");
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
String inner = (String) hints.remove(KEY_ELEMENT_INNERSVG);
if (title != null || inner != null) {
buf.append(">\n");
addInner(title, inner);
buf.append("</path>\n");
} else {
buf.append("/>\n");
}
}
/**
* Draw text
* @param color null to let CSS do it
* @param font null to let CSS do it
* @param clipid as returned from defineClipID() or null for none
* @param hints non-null
*/
public void drawText(String text, int x, int y, Color color, Font font, String clipid, Map<Object, Object> hints) {
buf.append("<text ");
addAttributes(hints);
addClipPath(clipid);
addInt("x", x);
addInt("y", y);
addStroke("fill", color, null);
if (font != null) {
addString("font-family", font.getFamily());
buf.append("font-size=\"").append(font.getSize()).append("px\" ");
if (font.isBold())
buf.append("font-weight=\"bold\" ");
if (font.isItalic())
buf.append("font-style=\"italic\" ");
}
buf.append("text-rendering=\"optimizeLegibility\">").append(DataHelper.escapeHTML(text));
String title = (String) hints.remove(KEY_ELEMENT_TITLE);
if (title != null)
addInner(title, null);
buf.append("</text>\n");
}
private void addInt(String key, int val) {
buf.append(key).append("=\"").append(val).append("\" ");
}
private void addString(String key, String val) {
buf.append(key).append("=\"").append(DataHelper.escapeHTML(val)).append("\" ");
}
/**
* @param id CSS id or null for none
* @param clz CSS class or null for none
*/
private void addIDClass(String id, String clz) {
if (id != null)
addString("id", id);
if (clz != null)
addString("class", clz);
}
private void addAttributes(Map<Object, Object> hints) {
String id = (String) hints.remove(KEY_ELEMENT_ID);
if (id != null)
addString("id", id);
String clz = (String) hints.remove(KEY_ELEMENT_CLASS);
if (clz != null)
addString("class", clz);
Map<?,?> atts = (Map) hints.remove(KEY_ELEMENT_ATTMAP);
if (atts != null) {
for (Map.Entry e : atts.entrySet()) {
addString((String) e.getKey(), (String) e.getValue());
}
}
}
/**
* @param type "fill" or "stroke"
* @param color null to let CSS do it
* @param stroke null to omit for fill
*/
private void addStroke(String type, Color color, BasicStroke stroke) {
buf.append(type);
if (color != null) {
// todo getRGB() #tohex & 0xffffff
//buf.append("=\"rgb(").append(color.getRed())
// .append(',').append(color.getGreen())
// .append(',').append(color.getBlue())
// .append(")\" ");
buf.append("=\"#").append(String.format(Locale.US, "%06x", color.getRGB() & 0xffffff))
.append("\" ");
int alpha = color.getAlpha();
if (alpha < 255) {
buf.append(type).append("-opacity=\"")
.append(String.format(Locale.US, "%.2f", alpha / 255f))
.append("\" ");
}
} else {
// default is black opaque, so fixup for none
buf.append("=\"none\" ");
}
if (stroke != null) {
int width = (int) stroke.getLineWidth();
if (width > 0) {
if (width != 1)
buf.append(type).append("-width=\"").append(width).append("\" ");
float[] dash = stroke.getDashArray();
if (dash != null && dash.length > 1) {
buf.append("stroke-dasharray=\"");
for (int i = 0; i < dash.length; i++) {
buf.append((int) dash[i]);
if (i != dash.length - 1)
buf.append(' ');
}
buf.append("\" ");
}
}
}
}
/**
* @param clipid as received from defineClipPath() or null for none
*/
private void addClipPath(String clipid) {
if (clipid != null)
buf.append("clip-path='url(#").append(clipid).append(")' ");
}
/**
* @param title, will be XML escaped here, or null
* @param other full elements, must be XML escaped, or null
*/
private void addInner(String title, String inner) {
if (title != null)
buf.append(" <title>").append(DataHelper.escapeHTML(title)).append("</title>\n");
if (inner != null)
buf.append(" ").append(inner).append("\n");
}
/*
public void main(String[] args) {
StringBuilder buf = new StringBuilder(2048);
SimpleSVGMaker g = new SimpleSVGMaker(buf);
Font f = new Font("Dialog", Font.BOLD, 24);
Color c = new Color(255, 128, 128);
g.startSVG(190, 200, c, "id", "class");
g.startGroup("gid", "class", "transform", "matrix");
c = new Color(255, 0, 0);
BasicStroke s = new BasicStroke(4);
Map<Object,Object> hints = new java.util.HashMap<Object,Object>();
g.drawSquare(100, 36, 17, null, c, s, null, hints);
c = new Color(33, 33, 33, 128);
s = new BasicStroke(8);
g.drawCircle(75, 56, 27, c, null, s, null, hints);
g.drawCircle(100, 100, 110, c, null, s, null, hints);
c = new Color(0, 255, 0);
s = new BasicStroke(2);
g.drawLine(55, 96, 97, 178, c, s, null, hints);
int[] xx = { 10, 20, 30, 40, 150 };
int[] yy = { 81, 92, 113, 184, 29 };
c = new Color(0, 0, 255);
s = new BasicStroke(2);
g.drawPolyline(xx, yy, 5, c, s, null, hints);
Color cc = new Color(128, 128, 0, 128);
Color ccc = new Color(128, 0, 192, 128);
g.drawRect(100, 80, 40, 20, cc, ccc, s, null, hints);
c = new Color(0, 128, 128);
g.drawText("foo", 135, 156, c, f, null, hints);
c = new Color(128, 128, 0);
f = new Font(Font.SANS_SERIF, Font.ITALIC, 20);
g.drawText("bar", 115, 136, c, f, null, hints);
f = new Font(Font.SANS_SERIF, Font.PLAIN, 16);
g.drawText("baz", 115, 176, c, f, null, hints);
g.endGroup();
g.endSVG();
System.out.print(buf.toString());
}
*/
}

View File

@ -0,0 +1,7 @@
<html>
<body>
<p>
SVG renderer and adapter for rrd4j. Since 0.9.64.
</p>
</body>
</html>

View File

@ -1,179 +0,0 @@
package org.rrd4j.data;
import org.rrd4j.core.Util;
import java.util.Calendar;
import java.util.Date;
/**
* Class used to interpolate datasource values from the collection of (timestamp, values)
* points using natural cubic spline interpolation.
* <p>
*
* <b>WARNING</b>: So far, this class cannot handle NaN datasource values
* (an exception will be thrown by the constructor). Future releases might change this.
*/
@SuppressWarnings("deprecation")
public class CubicSplineInterpolator extends Plottable {
private final double[] x;
private final double[] y;
// second derivates come here
private double[] y2;
// internal spline variables
private int n, klo, khi;
/**
* Creates cubic spline interpolator from arrays of timestamps and corresponding
* datasource values.
*
* @param timestamps timestamps in seconds
* @param values corresponding datasource values
* @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
* timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
*/
public CubicSplineInterpolator(long[] timestamps, double[] values) {
this.x = new double[timestamps.length];
for (int i = 0; i < timestamps.length; i++) {
this.x[i] = timestamps[i];
}
this.y = values;
validate();
spline();
}
/**
* Creates cubic spline interpolator from arrays of Date objects and corresponding
* datasource values.
*
* @param dates Array of Date objects
* @param values corresponding datasource values
* @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
* timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
*/
public CubicSplineInterpolator(Date[] dates, double[] values) {
this.x = new double[dates.length];
for (int i = 0; i < dates.length; i++) {
this.x[i] = Util.getTimestamp(dates[i]);
}
this.y = values;
validate();
spline();
}
/**
* Creates cubic spline interpolator from arrays of GregorianCalendar objects and corresponding
* datasource values.
*
* @param dates Array of GregorianCalendar objects
* @param values corresponding datasource values
* @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
* timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
*/
public CubicSplineInterpolator(Calendar[] dates, double[] values) {
this.x = new double[dates.length];
for (int i = 0; i < dates.length; i++) {
this.x[i] = Util.getTimestamp(dates[i]);
}
this.y = values;
validate();
spline();
}
/**
* Creates cubic spline interpolator for an array of 2D-points.
*
* @param x x-axis point coordinates
* @param y y-axis point coordinates
* @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
* timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
*/
public CubicSplineInterpolator(double[] x, double[] y) {
this.x = x;
this.y = y;
validate();
spline();
}
private void validate() {
boolean ok = true;
if (x.length != y.length || x.length < 3) {
ok = false;
}
for (int i = 0; i < x.length - 1 && ok; i++) {
if (x[i] >= x[i + 1] || Double.isNaN(y[i])) {
ok = false;
break;
}
}
if (!ok) {
throw new IllegalArgumentException("Invalid plottable data supplied");
}
}
private void spline() {
n = x.length;
y2 = new double[n];
double[] u = new double[n - 1];
y2[0] = y2[n - 1] = 0.0;
u[0] = 0.0; // natural spline
for (int i = 1; i <= n - 2; i++) {
double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
double p = sig * y2[i - 1] + 2.0;
y2[i] = (sig - 1.0) / p;
u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
}
for (int k = n - 2; k >= 0; k--) {
y2[k] = y2[k] * y2[k + 1] + u[k];
}
// prepare everything for getValue()
klo = 0;
khi = n - 1;
}
/**
* Calculates spline-interpolated y-value for the corresponding x-value. Call
* this if you need spline-interpolated values in your code.
*
* @param xval x-value
* @return inteprolated y-value
*/
public double getValue(double xval) {
if (xval < x[0] || xval > x[n - 1]) {
return Double.NaN;
}
if (xval < x[klo] || xval > x[khi]) {
// out of bounds
klo = 0;
khi = n - 1;
}
while (khi - klo > 1) {
// find bounding interval using bisection method
int k = (khi + klo) / 2;
if (x[k] > xval) {
khi = k;
}
else {
klo = k;
}
}
double h = x[khi] - x[klo];
double a = (x[khi] - xval) / h;
double b = (xval - x[klo]) / h;
return a * y[klo] + b * y[khi] +
((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0;
}
/**
* {@inheritDoc}
*
* Method overridden from the base class. This method will be called by the framework. Call
* this method only if you need spline-interpolated values in your code.
*/
public double getValue(long timestamp) {
return getValue((double)timestamp);
}
}

View File

@ -147,8 +147,7 @@ public class RrdGraph implements RrdGraphConstants {
drawAxis();
drawText();
drawLegend();
drawRules();
drawSpans();
drawRulesAndSpans();
gator();
drawOverlay();
saveImage();
@ -219,13 +218,17 @@ public class RrdGraph implements RrdGraphConstants {
}
}
private void drawRules() {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
private void drawRulesAndSpans() {
boolean found = false;
for (PlotElement pe : gdef.plotElements) {
if (pe instanceof HRule) {
HRule hr = (HRule) pe;
if (hr.value >= im.minval && hr.value <= im.maxval) {
int y = mapper.ytr(hr.value);
if (!found) {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
found = true;
}
worker.drawLine(im.xorigin, y, im.xorigin + im.xsize, y, hr.color, hr.stroke);
}
}
@ -233,31 +236,37 @@ public class RrdGraph implements RrdGraphConstants {
VRule vr = (VRule) pe;
if (vr.timestamp >= im.start && vr.timestamp <= im.end) {
int x = mapper.xtr(vr.timestamp);
if (!found) {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
found = true;
}
worker.drawLine(x, im.yorigin, x, im.yorigin - im.ysize, vr.color, vr.stroke);
}
}
}
worker.reset();
}
private void drawSpans() {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
for (PlotElement pe : gdef.plotElements) {
if (pe instanceof HSpan) {
else if (pe instanceof HSpan) {
HSpan hr = (HSpan) pe;
int ys = mapper.ytr(hr.start);
int ye = mapper.ytr(hr.end);
int height = ys - ye;
if (!found) {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
found = true;
}
worker.fillRect(im.xorigin, ys - height, im.xsize, height, hr.color);
}
else if (pe instanceof VSpan) {
VSpan vr = (VSpan) pe;
int xs = mapper.xtr(vr.start);
int xe = mapper.xtr(vr.end);
if (!found) {
worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
found = true;
}
worker.fillRect(xs, im.yorigin - im.ysize, xe - xs, im.ysize, vr.color);
}
}
worker.reset();
if (found)
worker.reset();
}
private void drawText() {
@ -726,9 +735,15 @@ public class RrdGraph implements RrdGraphConstants {
if (c instanceof LegendText) {
// draw with BOX
worker.fillRect(x, y - box, box, box, gdef.getColor(ElementsNames.frame));
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, gdef.getColor(ElementsNames.canvas));
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, gdef.getColor(ElementsNames.back));
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, ((LegendText) c).legendColor);
Color bc = (Color) gdef.getColor(ElementsNames.back);
Color lc = (Color) ((LegendText) c).legendColor;
// no use drawing unless both the two on top have some transparency
if (bc.getAlpha() < 255 && lc.getAlpha() < 255)
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, gdef.getColor(ElementsNames.canvas));
// no use drawing unless the one on top has some transparency
if (lc.getAlpha() < 255)
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, bc);
worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, lc);
worker.drawString(c.resolvedText, x + boxSpace, y, gdef.getFont(FONTTAG_LEGEND), gdef.getColor(ElementsNames.font));
}
else {

View File

@ -42,14 +42,12 @@ public class HostCheckHandler extends GzipHandler
_context = ctx;
_portMapper = ctx.portMapper();
_listenHosts = new HashSet<String>(8);
setMinGzipSize(64*1024);
setMinGzipSize(32*1024);
if (_context.getBooleanPropertyDefaultTrue(PROP_GZIP)) {
addIncludedMimeTypes(
// our js is very small
//"application/javascript", "application/x-javascript",
"application/javascript", "application/x-javascript",
"application/xhtml+xml", "application/xml",
// ditto svg
//"image/svg+xml",
"image/svg+xml",
"text/css", "text/html", "text/plain"
);
} else {

View File

@ -45,7 +45,7 @@ public class StatSummarizer implements Runnable, ClientApp {
private final Log _log;
/** list of SummaryListener instances */
private final List<SummaryListener> _listeners;
private static final int MAX_CONCURRENT_PNG = SystemVersion.isSlow() ? 1 : 3;
private static final int MAX_CONCURRENT_PNG = SystemVersion.isSlow() ? 3 : 8;
private final Semaphore _sem;
private volatile boolean _isRunning;
private volatile Thread _thread;

View File

@ -19,6 +19,7 @@ import javax.imageio.stream.MemoryCacheImageOutputStream;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.rrd4j.SimpleSVGImageWorker;
import net.i2p.router.RouterContext;
import net.i2p.router.util.EventLog;
import static net.i2p.router.web.GraphConstants.*;
@ -374,7 +375,8 @@ class SummaryRenderer {
RrdGraph graph;
try {
// NPE here if system is missing fonts - see ticket #915
graph = new RrdGraph(def);
SimpleSVGImageWorker svg = new SimpleSVGImageWorker(width, height);
graph = new RrdGraph(def, svg);
} catch (NullPointerException npe) {
_log.error("Error rendering graph", npe);
StatSummarizer.setDisabled(_context);
@ -385,13 +387,8 @@ class SummaryRenderer {
StatSummarizer.setDisabled(_context);
throw new IOException("Error rendering - disabling graph generation. Missing font?");
}
int totalWidth = graph.getRrdGraphInfo().getWidth();
int totalHeight = graph.getRrdGraphInfo().getHeight();
BufferedImage img = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_USHORT_565_RGB);
Graphics gfx = img.getGraphics();
graph.render(gfx);
ios = new MemoryCacheImageOutputStream(out);
ImageIO.write(img, "png", ios);
out.write(graph.getRrdGraphInfo().getBytes());
out.flush();
_context.statManager().addRateData("graph.renderTime", System.currentTimeMillis() - begin);
} catch (RrdException re) {

View File

@ -1,5 +1,4 @@
<%@page contentType="text/html"%>
<%@page trimDirectiveWhitespaces="true"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html><head>
@ -55,6 +54,7 @@ input.default {
<div id="langsettings">
<jsp:getProperty name="uihelper" property="langSettings" />
<p id="helptranslate"><%=uihelper._t("Please contribute to the router console translation project! Contact the developers in #i2p-dev on IRC to help.")%>
<%=uihelper._t("See the {0}translation status report{1}.", "<a href=\"/debug?d=6\">", "</a>")%>
</p><hr><div class="formaction" id="langui">
<input type="reset" class="cancel" value="<%=intl._t("Cancel")%>" >
<input type="submit" name="foo" class="accept" value="<%=intl._t("Apply")%>" >

View File

@ -22,6 +22,7 @@
<span class="tab"><a href="/debug?d=3">Router Session Key Manager</a></span>
<span class="tab"><a href="/debug?d=4">Client Session Key Managers</a></span>
<span class="tab"><a href="/debug?d=5">Router DHT</a></span>
<span class="tab"><a href="/debug?d=6">Translation Status</a></span>
</div>
<%
@ -116,6 +117,27 @@ if (dd == null || dd.equals("0")) {
out.print("<h2 id=\"dht\">Router DHT</h2>");
ctx.netDb().renderStatusHTML(out);
} else if (dd.equals("6")) {
/*
* Print out the status of the translations
*/
java.io.InputStream is = this.getClass().getResourceAsStream("/net/i2p/router/web/resources/translationstatus.html");
if (is == null) {
out.println("Translation status not available");
} else {
java.io.Reader br = null;
try {
br = new java.io.InputStreamReader(is, "UTF-8");
char[] buf = new char[4096];
int read;
while ( (read = br.read(buf)) >= 0) {
out.write(buf, 0, read);
}
} finally {
if (br != null) try { br.close(); } catch (java.io.IOException ioe) {}
}
}
}
%>

View File

@ -5673,6 +5673,9 @@ div.app:hover .applabel {
color: #e6e6e7;
}
iframe {
min-height: 100vh;
}
/* end home page */
@ -5696,7 +5699,6 @@ iframe.iframed {
#i2ptunnelframe {
margin: 0 0 -5px;
height: 100vh !important;
}
@ -7545,6 +7547,25 @@ b.netdb_transport {
font-weight: bold;
}
.debug_tx_total, .debug_tx_resource, .debug_tx_file {
width: auto;
}
.debug_tx_total td:nth-child(3),
.debug_tx_total td:nth-child(4),
.debug_tx_resource td:nth-child(3),
.debug_tx_resource td:nth-child(4) {
text-align: right;
}
.debug_tx_center,
.debug_tx_total td:nth-child(2),
.debug_tx_resource td:nth-child(2),
.debug_tx_file td:nth-child(2),
.debug_tx_file td:nth-child(3) {
text-align: center !important;
}
#portmapper td:first-child {
font-weight: bold;
}

View File

@ -1455,7 +1455,6 @@ p:empty+.sb_notice {
#susidnsframe {
margin: 0 0 -2px;
min-height: 100vh !important;
width: 100%;
overflow: hidden;
}
@ -1468,7 +1467,6 @@ p:empty+.sb_notice {
#i2ptunnelframe {
margin: -4px 0 -1px;
overflow: hidden;
height: 100vh !important;
}
.main#embedded {
@ -5042,6 +5040,10 @@ div.footnote hr {
margin-right: 5px;
}
iframe {
min-height: 100vh;
}
iframe.iframed {
margin: 10px 0 0;
}
@ -7645,6 +7647,25 @@ b.netdb_transport {
color: #050;
}
.debug_tx_total, .debug_tx_resource, .debug_tx_file {
width: auto;
}
.debug_tx_total td:nth-child(3),
.debug_tx_total td:nth-child(4),
.debug_tx_resource td:nth-child(3),
.debug_tx_resource td:nth-child(4) {
text-align: right;
}
.debug_tx_center,
.debug_tx_total td:nth-child(2),
.debug_tx_resource td:nth-child(2),
.debug_tx_file td:nth-child(2),
.debug_tx_file td:nth-child(3) {
text-align: center !important;
}
/* end debug */

View File

@ -53,8 +53,9 @@ if ( !rendered && ((rs != null) || fakeBw) ) {
rendered = ss.getXML(rate, cout);
}
} else {
response.setContentType("image/png");
response.setHeader("Content-Disposition", "inline; filename=\"" + stat + ".png\"");
response.setContentType("image/svg+xml");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "inline; filename=\"" + stat + ".svg\"");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Accept-Ranges", "none");
// http://jira.codehaus.org/browse/JETTY-1346

View File

@ -54,6 +54,7 @@
<echo message=" updater200WithJbigi" />
<echo message=" updaterSmall: updater with the essentials only - no SAM, i2psnark, SusiMail, SusiDNS, or history.txt" />
<echo message=" updaterRouter: updater with the i2p.jar and router.jar only" />
<echo message=" translationReport: generate a translation status report" />
<echo message=" distclean: clean up all derived files" />
<!-- <echo message=" syndie: generate a standalone syndie install" /> -->
<echo message=" desktopgui: generate a standalone desktopgui install" />
@ -290,7 +291,7 @@
<ant dir="apps/i2psnark/java/" target="standalone" />
-->
</target>
<target name="build2" depends="builddep, jar, buildWEB" />
<target name="build2" depends="builddep, jar, buildWEB, bundleTranslationReport" />
<target name="buildSmall" depends="builddepSmall, jarSmall, buildWEB" />
<target name="buildclean" depends="distclean, build" />
@ -315,23 +316,23 @@
<copy file="apps/sam/java/build/sam.jar" todir="build/" />
</target>
<target name="buildSusiMail" depends="buildCore, buildJetty" >
<target name="buildSusiMail" depends="buildJetty" >
<ant dir="apps/susimail/" target="war" />
<copy file="apps/susimail/susimail.war" todir="build/" />
</target>
<!-- jar (not war) for testing only -->
<target name="buildSusiMailJar" depends="buildCore, buildJetty" >
<target name="buildSusiMailJar" depends="buildJetty" >
<ant dir="apps/susimail/" target="jar" />
<copy file="apps/susimail/susimail.jar" todir="build/" />
</target>
<target name="buildSusiDNS" depends="buildCore, buildJetty, buildImagegen, buildAddressbook" >
<target name="buildSusiDNS" depends="buildImagegen, buildAddressbook" >
<ant dir="apps/susidns/src" target="all" />
<copy file="apps/susidns/src/susidns.war" todir="build/" />
</target>
<target name="buildImagegen" depends="buildCore, buildJetty" >
<target name="buildImagegen" depends="buildJetty" >
<ant dir="apps/imagegen" target="build" />
<copy file="apps/imagegen/imagegen/build/imagegen.war" todir="build/" />
</target>
@ -368,7 +369,7 @@
<copy file="apps/i2ptunnel/java/build/i2ptunnel-ui.jar" todir="build/" />
</target>
<target name="buildI2PTunnel" depends="buildMinistreaming, buildJetty, buildImagegen" >
<target name="buildI2PTunnel" depends="buildMinistreaming, buildImagegen" >
<ant dir="apps/i2ptunnel/java/" target="build" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.jar" todir="build/" />
<copy file="apps/i2ptunnel/java/build/i2ptunnel.war" todir="build/" />
@ -421,7 +422,7 @@
<copy file="core/java/build/i2p.jar" todir="build/" />
</target>
<target name="buildJrobin" depends="buildProperties" >
<target name="buildJrobin" depends="buildCore" >
<ant dir="apps/jrobin/java/" target="jar" />
<copy file="apps/jrobin/java/build/jrobin.jar" todir="build/" />
</target>
@ -879,7 +880,7 @@
<group title="Imagegen Application" packages="com.docuverse.identicon:com.google.zxing:com.google.zxing.*:net.i2p.imagegen" />
<group title="Installer Utilities" packages="net.i2p.installer" />
<group title="Jetty Utilities" packages="net.i2p.jetty:net.i2p.servlet:net.i2p.servlet.*" />
<group title="RRD4J Library (jrobin.jar)" packages="org.rrd4j:org.rrd4j.*:com.tomgibara.crinch.hashing" />
<group title="RRD4J Library (jrobin.jar)" packages="org.rrd4j:org.rrd4j.*:com.tomgibara.crinch.hashing:net.i2p.rrd4j" />
<group title="SAM Bridge" packages="net.i2p.sam" />
<group title="SAM Demos" packages="net.i2p.sam.client" />
<group title="SusiDNS Application" packages="i2p.susi.dns:net.i2p.addressbook.servlet" />
@ -1205,6 +1206,8 @@
<ant dir="installer/tools/java" target="distclean" />
<delete dir="installer/lib/izpack5/patches/java/build" quiet="true" />
<delete dir="reproducible/build" />
<!-- custom langpacks -->
<delete dir="com" />
<!--
NOTE! We need to turn off the default excludes for these
patterns to work.
@ -1609,6 +1612,32 @@
<su3sign infile="i2pseeds.zip" sigtype="RESEED" outfile="i2pseeds.su3" su3.ver="${epoch}" />
</target>
<!-- text output -->
<target name="translationReport" depends="buildTools, builddep, jar, buildWEB" unless="no.bundle">
<java classname="net.i2p.util.TranslationStatus" fork="true" dir="build/" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/tools.jar" />
</classpath>
</java>
</target>
<!-- stuff html output into routerconsole.war -->
<target name="bundleTranslationReport" depends="buildTools, builddep, jar, buildWEB" unless="no.bundle">
<mkdir dir="build/txstatus/WEB-INF/classes/net/i2p/router/web/resources/" />
<java classname="net.i2p.util.TranslationStatus" fork="true" dir="build/" failonerror="true" output="build/txstatus/WEB-INF/classes/net/i2p/router/web/resources/translationstatus.html" logError="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/tools.jar" />
</classpath>
<arg value="-h" />
</java>
<jar destfile="build/routerconsole.war" update="true" duplicate="preserve">
<fileset dir="build/txstatus" />
</jar>
<echo message="Translation status report bundled in routerconsole.war" />
</target>
<!-- this is no longer required, izpack 4.3.0 supports headless installs with java -jar i2pinstall.exe -console -->
<!-- and this is no longer used by the SlackBuild -->
<target name="tarball" depends="preppkg">
@ -1897,6 +1926,15 @@
<target name="izpack5-patches" depends="ensureIzpack5, buildProperties" >
<ant dir="installer/lib/izpack5/patches/java/" target="jar" />
<!-- custom langpacks
Izpack tries to load the resource both from the classpath and the file system;
we do it this way because jaring them up and adding a pathelement to izpack5.lib.path doesn't work.
See installer/install5.xml for details.
-->
<mkdir dir="com/izforge/izpack/bin/langpacks/" />
<copy toDir="com/izforge/izpack/bin/langpacks/" >
<fileset dir="installer/lib/izpack5/patches/resources" />
</copy>
</target>
<target name="installer5" depends="izpack5-patches, preppkg, buildProperties, buildUtilityJar" >

View File

@ -3,7 +3,8 @@ package freenet.support.CPUInformation;
/**
* Moved out of CPUID.java
*
* Ref: http://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
* Ref: https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
* Ref: https://gmplib.org/repo/gmp/file/tip/config.guess
*
* @since 0.8.7
*/
@ -468,7 +469,7 @@ class AMDInfoImpl extends CPUIDCPUInfo implements AMDCPUInfo
}
break;
// Zen / Zen+ / Zen2 / Zen3 / Ryzen 3/5/7/9/Threadripper / EPYC
// Zen / Zen+ / Zen2 / Zen3 / Zen4 / Ryzen 3/5/7/9/Threadripper / EPYC
// untested
case 23:
case 25: {

View File

@ -4,7 +4,8 @@ package freenet.support.CPUInformation;
* Moved out of CPUID.java
*
* Ref: https://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbers
* Ref: http://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures
* Ref: https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures
* Ref: https://gmplib.org/repo/gmp/file/tip/config.guess
*
* @since 0.8.7
*/
@ -521,6 +522,8 @@ class IntelInfoImpl extends CPUIDCPUInfo implements IntelCPUInfo
case 0xa7: // Rocket Lake
case 0x97: // Alder Lake
case 0x9a: // Alder Lake
case 0xba: // Raptor Lake
case 0xb7: // Raptor Lake
{
CPUIDCPUInfo c = new CPUIDCPUInfo();
if (c.hasAVX2() && c.hasBMI1() && c.hasBMI2() &&

View File

@ -31,7 +31,7 @@ public class CoreVersion {
* Otherwise, the same as PUBLISHED_VERSION.
* RouterVersion.FULL_VERSION is suggested for display to the user.
*/
public final static String VERSION = "2.5.2";
public final static String VERSION = "2.6.0";
/**
* The version published in the netdb via StatisticsManager.
@ -48,7 +48,7 @@ public class CoreVersion {
*
* @since 0.9.46
*/
public final static String PUBLISHED_VERSION = "0.9.62";
public final static String PUBLISHED_VERSION = "0.9.63";
/**
* For Vuze.

View File

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFeTCCA2GgAwIBAgIEZZozujANBgkqhkiG9w0BAQ0FADBtMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwNbWVlaEBtYWlsLmky
cDAeFw0xNDA2MjgyMjQ5MDlaFw0yNDA2MjcyMjQ5MDlaMG0xCzAJBgNVBAYTAlhY
MQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1v
dXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1tZWVoQG1haWwuaTJw
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnVnmPE4uUvCky0yCnnVH
cJEDqzwDPupx0zr0YDlhZk5VOPPecx5haayJ/V6nXPc1aVVWn+CHfedcF2aBgN4K
5aBueS/l6l5WHcv02DofAqlTmyAws3oQeR1qoTuW24cKRtLR7h5bxv63f6bgp6e+
RihFNez6UxErnRPuJOJEO2Im6EgVp6fz7tQ7R35zxAUeES2YILPySvzy2vYm/EEG
jXX7Ap2A5svVo90xCMOeUZ/55vLsjyIshN+tV87U4xwvAkUmwsmWVHm3BQpHkI6z
zMJie6epB8Bqm0GYm0EcElJH4OCxGTvDLoghpswbuUO7iy3JSfoL7ZCnoiQdK9K4
yVVChj8lG+r7KaTowK96iZep+sZefjOt5VFGuW2Fi/WBv3ldiLlJAo/ZfrUM4+vG
fyNBXbl6bX87uTCGOT1p3dazo+zJMsAZ+Y93DlM/mDEWFa1kKNrs74syzaWEqF4L
KQE6VoYn80OOzafSigTVQgSwUtQtB0XGhMzJhyxU2XHWe1LFIy7Pta0B+lDiZj7c
I8nXxYjsDfEu/Elj/Ra9N6bH0awmgB5JDa+Tbir+oEM5SyDfpSaCGuatdGxjweGI
kVmFU0SqCZV/8TXbIu6MUVzTZMZVT94edifFSRad4fqw7eZbSXlPu++3d1/btn6h
ibM04nkv0mm+FxCKB/wdAkECAwEAAaMhMB8wHQYDVR0OBBYEFO7jIkSRkoXyJcho
9/Q0gDOINa5EMA0GCSqGSIb3DQEBDQUAA4ICAQBzfWO7+8HWOKLaYWToJ6XZbpNF
3wXv1yC4W/HRR80m4JSsq9r0d7838Nvd7vLVP6MY6MaVb/JnV76FdQ5WQ6ticD0Y
o3zmpqqbKVSspN0lrkig4surT88AjfVQz/vEIzKNQEbpzc3hC2LCiE2u+cK/ix4j
b9RohnaPvwLnew5RNQRpcmk+XejaNITISr2yQIwXL7TEYy8HdGCfzFSSFhKe9vkb
GsWS5ASrUzRoprswmlgRe8gEHI+d51Z7mWgna0/5mBz9bH/3QXtpxlLWm3bVV+kt
pZjQDTHE0GqG2YsD1Gmp4LU/JFhCojMTtiPCXmr9KFtpiVlx06DuKm5PC8Ak+5w+
m/DQYYfv9z+AA5Y430bjnzwg67bhqVyyek4wcDQinFswv3h4bIB7CJujDcEqXXza
lhG1ufPPCUTMrVjh7AShohZraqlSlyQPY9vEppLwD4W1d+MqDHM7ljOH7gQYaUPi
wE30AdXEOxLZcT3aRKxkKf2esNofSuUC/+NXQvPjpuI4UJKO3eegi+M9dbnKoNWs
MPPLPpycecWPheFYM5K6Ao63cjlUY2wYwCfDTFgjA5q8i/Rp7i6Z6fLE3YWJ4VdR
WOFB7hlluQ//jMW6M1qz6IYXmlUjcXl81VEvlOH/QBNrPvX3I3SYXYgVRnVGUudB
o3eNsanvTU+TIFBh2Q==
-----END CERTIFICATE-----

View File

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF0zCCA7ugAwIBAgIQWjHyC+NRh3emuuAwcEnKSjANBgkqhkiG9w0BAQsFADB0
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsGA1UEAwwU
cmVzZWVkQGRpdmEuZXhjaGFuZ2UwHhcNMjAwNjA5MDUzNjQ1WhcNMzAwNjA5MDUz
NjQ1WjB0MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4w
HAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsG
A1UEAwwUcmVzZWVkQGRpdmEuZXhjaGFuZ2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQC6BJGeMEgoXk9dlzKVfmwHrT2VpwTT+wRJvh3eAM746u4uDT2y
NPHXhdGcQ9dRRZ63T98IshWCwOmWSlm1kdWkmKkVVb93GUoMQ3gziCi0apLJMAau
gEu/sPCbORS2dPsQeAPW2eIsJO7dSjTRiQAuquW//NcIXG4gnxDA52lgke1BvpKr
83SJlCrqECAy6OKtZ49yn75CqmPPWFn0b/E8bxruN5ffeipTTospvdEtT41gXUqk
hOz3k8ang+QTWiP//jOjk31KXZ2dbh0LOlNJOvRxCqQmBZafNxxCR4DH8RewfPlL
qOiOJVzbLSP9RjqPLwnny5BOjbLWXcaybN5Qv2Pyd4mKtN3EpqBwRu7VnzXpsuuG
gRbxNmfKJ/vBEGrZAHAxi0NkHHEEne3B7pPDc2dVZHOfTfCu31m9uDHZ4eHEsNOJ
SJRiGjq74l0chCSlBGLrD1Y9LPyqadjdwuB9bzM0tMFC1wPflanQCflhhnEzAfbN
BaU2GRXo/I1UCDW/dH1FIkqEe61eMW1Lwqr5tdlrUpdr5VIddTyNJRBJogbZ+HZE
8mcoJW2lXRAkYi7KEm4b4EQNe7sbRNTF0j+fAJ+3ZOZ3O3SMHss6ignlSa+giVim
VvL+Joc6wpSzxpeNPf6m82cEO/UvifFYeOC9TpiRriSt+vvgQVzQtfQ+fQIDAQAB
o2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
BwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHJlc2VlZEBkaXZhLmV4Y2hh
bmdlMA0GCSqGSIb3DQEBCwUAA4ICAQCFGOb1dHlwjmgFHEER6oMiGWl1mI3Hb7GX
NNI6QUhZQ+iEWGYtsOTk3Q8xejL8t6AG/ZLXfZviLIJXZc5XZfPXk0ezDSC2cYxQ
ZAyYPw2dRP14brI86sCSqNAFIax/U5SM3zXhCbBiTfaEoBPfDpvKjx+VliaITUnc
sHTRn+C5ID5M8cZIqUSGECPEMU/bDtuRNJLTKYaJ98yXtYuS2CWsMEM4o0GGcnYQ
5HOZT/lbbwfq1Ks7IyJpeIpRaS5qckGcfgkxFY4eGujDuaFeWC+HCIh9RzBJrqZR
73Aly4Pyu7Jjg8xCCf9MswDjtqAjEHgWCmRLWL7p3H6cPipFKNMY6yomYZl5urE7
q6DUAZFKwPqlZpyeaY4/SVvaHTxuPp7484s3db4kPhdmuQS/DOB/7d+cn/S580Vy
ALqlFQjtjLEaT16upceAV0gYktDInE6Rtym/OsqilrtYks/Sc0GROSz8lJhDDWbr
W3t92muSXDh0rYrEUYWl+xl1gSTpbIP75zzU+cUr1E/qlRY9qZn66FsJpOuN0I0q
UXsQS/bPDcA+IW48Hd9LfO9gtTWZslwFTimjEvQ2nJAnUlUQP6OfuPUKHoYX/CwY
2LCN8+pv2bKPDVHvp0lf6xrbbZNvFtzfR0G3AprZjYpuu2XgjVB5nJnwmbH74b9w
LD8d2z2Lgg==
-----END CERTIFICATE-----

View File

@ -10,12 +10,12 @@ import org.scalatest.Matchers
class CertUtilSpec extends FunSpec with Matchers {
describe("CertUtil") {
val certFileUrl = getClass.getResource("/meeh_at_mail.i2p.crt")
val certFileUrl = getClass.getResource("/reseed_at_diva.exchange.crt")
val certFile = new File(certFileUrl.toURI)
it("should be able to read a certificate") {
val cert: X509Certificate = CertUtil.loadCert(certFile)
assert(cert.getSubjectDN.toString === "CN=meeh@mail.i2p, OU=I2P, O=I2P Anonymous Network, L=XX, ST=XX, C=XX")
assert(cert.getSubjectDN.toString === "CN=reseed@diva.exchange, OU=I2P, O=I2P Anonymous Network, STREET=XX, L=XX, C=XX")
}
it("should be able to tell if it's revoked or not") {

View File

@ -17,7 +17,7 @@ class SU3FileSpec extends FunSpec with Matchers {
}
describe("SU3File") {
val certFileUrl = getClass.getResource("/meeh_at_mail.i2p.crt")
val certFileUrl = getClass.getResource("/reseed_at_diva.exchange.crt")
val certFile = new File(certFileUrl.toURI)
val seedFileUrl = getClass.getResource("/i2pseeds.su3")

View File

@ -1,3 +1,9 @@
i2p (2.6.0-1~bionic+1) bionic; urgency=medium
* New upstream version 2.6.0
-- idk <hankhill19580@gmail.com> Wed, 20 July 2024 12:40:12 +0000
i2p (2.5.2-1~bionic+1) bionic; urgency=medium
* New upstream version 2.5.2

View File

@ -1,3 +1,9 @@
i2p (2.6.0-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.0
-- idk <hankhill19580@gmail.com> Wed, 20 July 2024 12:40:12 +0000
i2p (2.5.2-1ubuntu1) focal; urgency=medium
* New upstream version 2.5.2

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
i2p (2.6.0-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.0
-- idk <hankhill19580@gmail.com> Wed, 20 July 2024 12:12:12 +0000
i2p (2.5.2-1~ubuntu1) focal; urgency=medium
* New upstream version 2.5.2

View File

@ -1,3 +1,19 @@
2024-07-25 zzz
* Console:
- Add translation status report (Gitlab MR !207)
- Convert graphs to SVG (Gitlab MR !208)
- Enable compression of js and svg files
* i2ptunnel: Additional fixes for invalid entries in filter file (Gitlab #483)
* imagegen: Convert identicons to SVG
* Installer: Fix some izpack5 translated languages
* rrd4j: More optimizations for graph generation
* Util: Add new processors for CPUID
2024-07-19 2.6.0 (API 0.9.63) released
2024-07-19 idk
* Fix failing integration tests
2024-07-15 zzz
* Pull translations from Transifex

View File

@ -4,7 +4,7 @@
<info>
<appname>i2p</appname>
<appversion>2.5.2</appversion>
<appversion>2.6.0</appversion>
<authors>
<author name="I2P" email="https://geti2p.net/"/>
</authors>

View File

@ -10,7 +10,7 @@
<info>
<appname>i2p</appname>
<appversion>2.5.2</appversion>
<appversion>2.6.0</appversion>
<authors>
<author name="I2P" email="https://geti2p.net/"/>
</authors>
@ -34,19 +34,81 @@ https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491730/GUI+Preferences
<modifier key="langDisplayType" value="native" />
</guiprefs>
<!--
Locales:
This is poorly documented, like a lot of things in izpack, but these can
be 2 OR 3 character country OR language codes.
Whatever it is, there must be xx.xml and xx.gif files available at
build time or the build will error out.
At runtime, izpack loads all the JVM's locales and tries to find
the "best match" locale for the code. See izpack DefaultLocales.java.
It then uses Locale.getDisplayLanguage() on that best match to show the (translated) language name
when langDisplayType=native, which we set in guiprefs above.
At https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491613/Overriding+Built-in+Translations
it says:
"In IzPack, language packs are identified by a 3 character ISO country or language code.
Country codes are converted to lowercase.
Country codes are used in preference to language codes.
This is to handle the case where a language variation is spoken for which there is no ISO language code."
This is wrong in that 2-character country and language codes are also allowed.
It is also wrong in that, unfortunately,
country codes combined with "best match" can go very badly.
Izpack 4 used the language code "ind" for Indonesian, but
Izpack 5 switched to use the country code "idn" instead.
This worked fine on Java 8, but on Java 21, the best match finds Javanese/Jawa for "idn",
which is a completely different language than Indonesian.
See: https://old.reddit.com/r/i2p/comments/1e61lsp/wrong_country_name_indonesia_as_jawa/
Renamed or custom langpacks (xml + gif) must be checked in to
installer/lib/izpack5/patches/resources
and may then be added below, and will be bundled with the installer.
Note that the JVM's installed locales varies widely by Java version.
For example, as of 2024 on Ubuntu, Java 8 has 159 locales and Java 21 has 1050.
The selected locale may even depend on the ordering of locales returned by getAvailableLocales() in the JVM.
If no locale for any code is found, it outputs "WARNING: No locale for xx"
which is annoying. Even worse, if no locale found, it doesn't display the translation
as an option.
But that shouldn't stop us from including it if some JVMs have it.
-->
<locale>
<langpack iso3="eng"/>
<!--
Brazilian Portuguese
see above, wrongly matches neegatu, replaced by por.
Portuguese (Portugal) is prt below.
<langpack iso3="bra"/>
-->
<langpack iso3="por"/>
<langpack iso3="cat"/>
<langpack iso3="ces"/>
<!--
Chinese
see above, wrongly matches Sichuan Yi (iii), replaced by zho
<langpack iso3="chn"/>
-->
<langpack iso3="zho"/>
<langpack iso3="dan"/>
<langpack iso3="deu"/>
<langpack iso3="ell"/>
<!-- fa not found in older JVMs, may generate warning, see above -->
<langpack iso3="fa"/>
<langpack iso3="fin"/>
<langpack iso3="fra"/>
<langpack iso3="hun"/>
<!--
see above, replaced by ind
<langpack iso3="idn"/>
-->
<langpack iso3="ind"/>
<langpack iso3="ita"/>
<langpack iso3="jpn"/>
<langpack iso3="kor"/>
@ -65,10 +127,10 @@ https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491730/GUI+Preferences
<langpack iso3="twn"/>
<langpack iso3="ukr"/>
<!--
At runtime, if the JVM does not have a locale:
"WARNING: No locale for:"
<langpack iso3="eus"/>
<langpack iso3="fa"/>
<langpack iso3="glg"/>
<langpack iso3="eus"/> Basque
<langpack iso3="glg"/> Galician
-->
</locale>

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

View File

@ -0,0 +1,352 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<!-- The Indonesian langpack -->
<!-- translation provided by Thomas Edwin Santosa - thomas (at) katalisindonesia dot com-->
<izpack:langpack version="5.0"
xmlns:izpack="http://izpack.org/schema/langpack"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://izpack.org/schema/langpack http://izpack.org/schema/5.0/izpack-langpack-5.0.xsd">
<!-- Heading messages START -->
<str id="CheckedHelloPanel.headline" txt="Selamat Datang"/>
<str id="CompilePanel.headline" txt="Kompilasi Kode Sumber Java"/>
<str id="ConditionalUserInputPanel.headline" txt="Data Pengguna"/>
<str id="FinishPanel.headline" txt="Pemasangan Telah Selesai"/>
<str id="HelloPanel.headline" txt="Selamat Datang"/>
<str id="HTMLInfoPanel.headline" txt="Informasi"/>
<str id="HTMLLicencePanel.headline" txt="Perjanjian Lisensi"/>
<str id="PDFLicencePanel.headline" txt="Perjanjian Lisensi"/>
<str id="ImgPacksPanel.headline" txt="Pilih Paket-Paket Pemasangan"/>
<str id="InfoPanel.headline" txt="Informasi"/>
<str id="InstallPanel.headline" txt="Pemasangan"/>
<str id="JDKPathPanel.headline" txt="Alamat JDK"/>
<str id="LicencePanel.headline" txt="Perjanjian Lisensi"/>
<str id="PacksPanel.headline" txt="Pilih Paket-Paket Pemasangan"/>
<str id="ProcessPanel.headline" txt="Lakukan Proses-Proses Eksternal"/>
<str id="ShortcutPanel.headline" txt="Jalan-Jalan Pintas"/>
<str id="SimpleFinishPanel.headline" txt="Pemasangan Telah Selesai"/>
<str id="SummaryPanel.headline" txt="Ringkasan Data Konfigurasi"/>
<str id="TargetPanel.headline" txt="Alamat Tujuan"/>
<str id="TreePacksPanel.headline" txt="Pilih Paket-Paket Pemasangan"/>
<str id="UserInputPanel.headline" txt="Data Pengguna"/>
<str id="UserPathPanel.headline" txt="Pilih Lokasi"/>
<str id="InstallationTypePanel.headline" txt="Jenis Pemasangan"/>
<!-- ConsolePrompt strings -->
<str id="ConsolePrompt.okCancel" txt="Enter O for OK, C to Cancel: "/>
<str id="ConsolePrompt.yesNo" txt="Enter Y for Yes, N for No: "/>
<str id="ConsolePrompt.yesNoCancel" txt="Enter Y for Yes, N for No, or C to Cancel: "/>
<str id="ConsolePrompt.ok" txt="O"/>
<str id="ConsolePrompt.cancel" txt="C"/>
<str id="ConsolePrompt.yes" txt="Y"/>
<str id="ConsolePrompt.no" txt="N"/>
<!-- ConsoleInstaller strings -->
<str id="ConsoleInstaller.continueQuitRedisplay" txt="Press 1 to continue, 2 to quit, 3 to redisplay"/>
<str id="ConsoleInstaller.acceptRejectRedisplay" txt="Press 1 to accept, 2 to reject, 3 to redisplay"/>
<str id="ConsoleInstaller.redisplayQuit" txt="Press 1 to redisplay, 2 to quit"/>
<str id="ConsoleInstaller.permissionError" txt="Administrative privileges required. Please re-run the installer with administrative privileges."/>
<str id="ConsoleInstaller.inputSelection" txt="Input selection: "/>
<str id="ConsoleInstaller.pagingMore" txt="More"/>
<str id="ConsoleInstaller.aborted.PressedCTRL-C" txt="CTRL-C pressed"/>
<str id="ConsoleInstaller.aborted.LicenseRejected" txt="License rejected"/>
<str id="ConsoleInstaller.aborted.PressedQuit" txt="Quit pressed"/>
<str id="ConsoleInstaller.shutdown.pendingFileOperations" txt="There are file operations pending after reboot"/>
<str id="ConsoleInstaller.shutdown.rebootingNow" txt="Rebooting now automatically"/>
<str id="ConsoleInstaller.shutdown.done" txt="Console installation done"/>
<str id="ConsoleInstaller.shutdown.aborted" txt="Console installation ABORTED by the user!"/>
<str id="ConsoleInstaller.shutdown.failed" txt="Console installation FAILED!"/>
<!-- General installer strings -->
<str id="installer.title" txt="IzPack - Pemasangan "/>
<str id="installer.next" txt="Berikut"/>
<str id="installer.prev" txt="Sebelum"/>
<str id="installer.quit" txt="Keluar"/>
<str id="installer.madewith" txt="(Dibuat dengan IzPack- http://izpack.org/)"/>
<str id="installer.quit.title" txt="Apakah Anda yakin ingin keluar?"/>
<str id="installer.quit.message" txt="Ini akan membatalkan pemasangan!"/>
<str id="installer.warning" txt="Peringatan!"/>
<str id="installer.yes" txt="Ya"/>
<str id="installer.no" txt="Tidak"/>
<str id="installer.cancel" txt="Batal"/>
<str id="installer.error" txt="Kesalahan"/>
<str id="installer.help" txt="Pertolongan"/>
<str id="installer.help.close" txt="Tutup"/>
<str id="installer.of" txt="dari"/>
<str id="installer.step" txt="Langkah"/>
<str id="installer.Message" txt="Pesan"/>
<str id="installer.errorMessage" txt="An error occured"/>
<str id="installer.close" txt="Close"/>
<str id="installer.showDetails" txt="Show Details"/>
<str id="installer.hideDetails" txt="Hide Details"/>
<str id="installer.copy" txt="Copy"/>
<str id="installer.sendReport" txt="Send Report"/>
<str id="installer.continueQuestion" txt="Continue anyway?"/>
<str id="installer.cancelled" txt="Installation cancelled"/>
<str id="installer.started" txt="Installation started"/>
<str id="installer.platform" txt="Platform: {0}"/>
<str id="installer.version" txt="Framework: {0}"/>
<str id="installer.finished" txt="Installation finished"/>
<!-- Uninstaller specific strings -->
<str id="uninstaller.warning" txt="Ini akan menghapus aplikasi terpasang!"/>
<str id="uninstaller.destroytarget" txt=" Memaksa penghapusan "/>
<str id="uninstaller.uninstall" txt="Penghapusan"/>
<!-- The strings for the 'official' IzPack plugins -->
<str id="HelloPanel.welcome1" txt="Selamat datang ke pemasangan "/>
<str id="HelloPanel.welcome2" txt="!"/>
<str id="HelloPanel.authors" txt="Perangkat lunak ini dikembangkan oleh: "/>
<str id="HelloPanel.url" txt="Halaman rumah berada di: "/>
<str id="PrinterSelectPanel.select_printer"
txt="Pilihlah printer yang digunakan untuk pemasangan awal dan pengetesan."/>
<str id="CheckedHelloPanel.productAlreadyExist0" txt="Produk ini sudah terpasang di komputer ini pada lokasi "/>
<str id="CheckedHelloPanel.productAlreadyExist1" txt=" . Apakah Anda yakin untuk memasang entitas lain?"/>
<str id="CheckedHelloPanel.infoOverUninstallKey" txt="Kunci penghapusan akan dinamai: "/>
<str id="LicencePanel.info" txt="Silakan baca perjanjian lisensi berikut dengan seksama:"/>
<str id="LicencePanel.agree" txt="Saya menerima syarat-syarat dan kondisi-kondisi perjanjian lisensi ini."/>
<str id="LicencePanel.notagree"
txt="Saya tidak menerima syarat-syarat dan kondisi-kondisi perjanjian lisensi ini."/>
<str id="LicencePanel.yes" txt="Ya"/>
<str id="LicencePanel.no" txt="Tidak"/>
<str id="InstallationTypePanel.info" txt="Silakan pilih jenis pemasangan:"/>
<str id="InstallationTypePanel.modify" txt="Mengubah pemasangan"/>
<str id="InstallationTypePanel.normal" txt="Pemasangan baru"/>
<str id="InfoPanel.info" txt="Silakan baca informasi berikut: "/>
<str id="PathInputPanel.required" txt="Direktori yang terpilih seharusnya ada."/>
<str id="PathInputPanel.required.forModificationInstallation" txt="Direktori terpilih harus ada."/>
<str id="PathInputPanel.notValid" txt="Direktori terpilih tidak mengandung produk yang diperlukan."/>
<str id="TargetPanel.info" txt="Silakan pilih lokasi pemasangan: "/>
<str id="TargetPanel.browse" txt="Jelajah..."/>
<str id="TargetPanel.warn"
txt="Direktori tersebut sudah ada! Apakah Anda yakin untuk melakukan pemasangan ke sana dan kemungkinan menimpa arsip-arsip yang telah ada?"/>
<str id="TargetPanel.empty_target"
txt="Anda belum menspesifikasi lokasi tujuan! Apakah betul?"/>
<str id="TargetPanel.createdir" txt="Direktori tujuan akan dibuat: "/>
<str id="TargetPanel.nodir"
txt="Arsip ini bukan direktori! Silakan pilih sebuah direktori!"/>
<str id="TargetPanel.notwritable"
txt="Direktori ini tidak dapat ditulisi! Silakan pilih direktori lain!"/>
<str id="JDKPathPanel.extendedIntro"
txt="Aplikasi yang telah dipasang membutuhkan sebuah JDK dengan versi antara ${JDKPathPanel.minVersion} dan ${JDKPathPanel.maxVersion}. Sebuah Java Runtime Environment (JRE) tidak cukup."/>
<str id="JDKPathPanel.intro"
txt="Instalasi yang terinstal membutuhkan JDK. Sebuah Java Runtime Environment (JRE) saja tidak akan cukup."/>
<str id="JDKPathPanel.info" txt="Silakan pilih alamat JDK:"/>
<str id="JDKPathPanel.badVersion1" txt="JDK yang terpilih memiliki versi yang salah (yang ada: "/>
<str id="JDKPathPanel.badVersion2" txt=" yang diperlukan: "/>
<str id="JDKPathPanel.badVersion3" txt=") apakah JDK ini tetap akan digunakan?"/>
<str id="JDKPathPanel.nonValidPathInReg"
txt="The Windows registry contains a non-valid path for this JDK. Should this JDK be used anyway?"/>
<str id="PacksPanel.info" txt="Silakan pilih paket-paket yang ingin Anda pasang:"/>
<str id="PacksPanel.tip" txt="Catatan: paket-paket yang berwarna kelabu diperlukan."/>
<str id="PacksPanel.space" txt="Jumlah ruang yang dibutuhkan: "/>
<str id="PacksPanel.freespace" txt="Ruang yang ada: "/>
<str id="PacksPanel.description" txt="Deskripsi"/>
<str id="PacksPanel.dependencyList"
txt="Paket yang terpilih membutuhkan paket-paket berikut dipasang "/>
<str id="PacksPanel.dependencies" txt="Ketergantungan: "/>
<str id="PacksPanel.excludes" txt="Pengecualian: "/>
<str id="ImgPacksPanel.dependencyList" txt="Ketergantungan"/>
<str id="PacksPanel.notEnoughSpace"
txt="Ruang cakram yang diperlukan untuk pemasangan melebihi ruang cakram yang tersedia."/>
<str id="PacksPanel.notAscertainable" txt="tidak dapat ditetapkan"/>
<str id="InstallPanel.info" txt="Klik 'Pasang!' untuk memulai proses pemasangan"/>
<str id="InstallPanel.install" txt="Pasang!"/>
<str id="InstallPanel.tip" txt="Perkembangan pemasangan paket:"/>
<str id="InstallPanel.begin" txt="[Tidak ada]"/>
<str id="InstallPanel.finished" txt="[Selesai]"/>
<str id="InstallPanel.progress" txt="Perkembangan pemasangan keseluruhan:"/>
<str id="InstallPanel.overwrite.title" txt="Arsip sudah ada"/>
<str id="InstallPanel.overwrite.question" txt="Arsip berikut sudah ada. Apakah akan ditimpa?"/>
<str id="FinishPanel.success" txt="Pemasangan telah selesai dengan sukses."/>
<str id="FinishPanel.done" txt="Selesai"/>
<str id="FinishPanel.fail" txt="Pemasangan gagal!"/>
<str id="FinishPanel.uninst.info" txt="Program penghapusan sudah dibuat di: "/>
<str id="FinishPanel.auto" txt="Buat naskah pemasangan otomatis"/>
<str id="FinishPanel.auto.tip"
txt="Gunakan naskah ini untuk mengulangi pemasangan ini ke komputer lain."/>
<str id="FinishPanel.auto.dialog.filterdesc" txt="Arsip-arsip XML"/>
<str id="ImgPacksPanel.packs" txt="Paket-paket berikut tersedia:"/>
<str id="ImgPacksPanel.snap" txt="Gambaran paket:"/>
<str id="ImgPacksPanel.checkbox" txt=" Pasang paket berikut"/>
<str id="ShortcutPanel.headline" txt="Pemasangan Jalan Pintas"/>
<str id="ShortcutPanel.regular.list" txt="Pilih Kelompok Program untuk Jalan Pintas:"/>
<str id="ShortcutPanel.regular.default" txt="Nilai awal"/>
<str id="ShortcutPanel.regular.desktop" txt="Buat jalan pintas di atas meja (desktop)"/>
<str id="ShortcutPanel.regular.StartMenu:Start-Menu" txt="Menu-Mulai"/>
<str id="ShortcutPanel.regular.StartMenu:K-Menu" txt="K-Menu"/>
<!-- "StartMenu" is a placeholder will be replaced at runtime -->
<str id="ShortcutPanel.regular.create" txt="Buat Jalan Pintas pada StartMenu"/>
<str id="ShortcutPanel.regular.userIntro" txt="buat jalan pintas untuk:"/>
<str id="ShortcutPanel.regular.currentUser" txt="pengguna sekarang"/>
<str id="ShortcutPanel.regular.allUsers" txt="semua pengguna"/>
<str id="ShortcutPanel.alternate.apology"
txt="Kami minta maaf karena IzPack tidak mendukung pembuatan jalan pintas di sistem operasi ini. Untuk membuat jalan pintas, silakan lihat petunjuk sistem operasi Anda."/>
<str id="ShortcutPanel.alternate.targetsLabel"
txt="Berikut ini adalah daftar tujuan-tujuan yang kami ingin Anda akses."/>
<str id="ShortcutPanel.alternate.textFileExplanation"
txt="Anda dapat menyimpan informasi terinci mengenai tujuan-tujuan aplikasi pada arsip teks untuk referensi di kemudian hari."/>
<str id="ShortcutPanel.alternate.saveButton" txt="Simpan Arsip Teks"/>
<str id="ShortcutPanel.textFile.header"
txt="Informasi Jalan Pintas\n======================\n\nBerikut ini adalah daftar semua informasi yang relevan tentang Jalan Pintas yang dimaksud. Informasi ini dapat digunakan untuk membuat jalan pintas secara manual.\n"/>
<str id="ShortcutPanel.textFile.name" txt="Jalan Pintas : "/>
<str id="ShortcutPanel.textFile.location" txt="Lokasi yang dimaksud : "/>
<str id="ShortcutPanel.textFile.description" txt="Dekripsi : "/>
<str id="ShortcutPanel.textFile.target" txt="Tujuan jalan pintas : "/>
<str id="ShortcutPanel.textFile.command" txt="Baris perintah : "/>
<str id="ShortcutPanel.textFile.iconName" txt="Arsip ikon : "/>
<str id="ShortcutPanel.textFile.iconIndex" txt="Indeks ikon : "/>
<str id="ShortcutPanel.textFile.work" txt="Direktori kerja : "/>
<str id="ShortcutPanel.location.desktop" txt="Atas Meja (Desktop)"/>
<str id="ShortcutPanel.location.applications" txt="Menu Aplikasi"/>
<str id="ShortcutPanel.location.startMenu" txt="Menu Awal"/>
<str id="ShortcutPanel.location.startup" txt="Grup Mulai Awal (Startup)"/>
<str id="UserInputPanel.error.caption" txt="Masalah Masukan"/>
<str id="UserInputPanel.search.autodetect" txt="Deteksi otomatis"/>
<str id="UserInputPanel.dir.nodirectory.message" txt="Anda harus memilih sebuah direktori yang sahih."/>
<str id="UserInputPanel.dir.nodirectory.caption" txt="Tidak Ada Direktori Terpilih"/>
<str id="UserInputPanel.dir.notdirectory.message"
txt="Direktori yang telah Anda pilih tidak ada atau tidak sahih."/>
<str id="UserInputPanel.dir.notdirectory.caption" txt="Direktori Tidak Sahih"/>
<str id="UserInputPanel.file.nofile.message" txt="Anda harus memilih sebuah berkas yang sahih."/>
<str id="UserInputPanel.file.nofile.caption" txt="Tidak Ada Berkas Terpilih"/>
<str id="UserInputPanel.file.notfile.message" txt="Berkas yang telah Anda pilih tidak ada atau tidak sahih."/>
<str id="UserInputPanel.file.notfile.caption" txt="Berkas Tidak Sahih"/>
<!-- more descriptive error message would be cool, like specifying what file we looked for -->
<str id="UserInputPanel.search.autodetect.failed.message" txt="Deteksi otomatis gagal."/>
<str id="UserInputPanel.search.autodetect.failed.caption" txt="Deteksi otomatis gagal."/>
<str id="UserInputPanel.search.autodetect.tooltip"
txt="Silakan periksa arsip atau direktori di alamat yang diberikan di atas."/>
<str id="UserInputPanel.search.location" txt="Masukkan lokasi {0}."/>
<str id="UserInputPanel.search.location.checkedfile" txt="Keberadaan {0} telah diperiksa."/>
<str id="UserInputPanel.search.browse" txt="Jelajah..."/>
<str id="UserInputPanel.search.wrongselection.message"
txt="Arsip atau direktori yang Anda pilih tidak ada atau tidak cocok."/>
<str id="UserInputPanel.search.wrongselection.caption" txt="Pilihan yang tidak sahih."/>
<str id="UserPathPanel.required" txt="Direktori terpilih harus ada."/>
<str id="UserPathPanel.info" txt="Pilih lokasi: "/>
<str id="UserPathPanel.browse" txt="Jelajah"/>
<str id="UserPathPanel.exists_warn"
txt="Direktori tersebut sudah ada! Apakah Anda yakin untuk melakukan pemasangan di sini dan kemungkinan menindih berkas yang telah ada?"/>
<str id="UserPathPanel.empty_target" txt="Anda belum menentukan lokasi target! Apakah benar?"/>
<str id="UserPathPanel.createdir" txt="Direktori target tersebut akan dibuat: "/>
<str id="UserPathPanel.nodir" txt="Berkas ini bukan suatu direktori! Silakan pilih suatu direktori!"/>
<str id="UserPathPanel.notwritable" txt="Direktori ini tidak dapat ditulisi! Silakan pilih direktori lain!"/>
<str id="CompilePanel.heading" txt="Kompilasi"/>
<str id="CompilePanel.tip" txt="Perkembangan pekerjaan kompilasi:"/>
<str id="CompilePanel.browse" txt="Jelajah..."/>
<str id="CompilePanel.browse.approve" txt="Gunakan sebagai kompiler"/>
<str id="CompilePanel.start" txt="Mulai"/>
<str id="CompilePanel.progress.initial" txt="[Silakan tekan tombol Mulai]"/>
<str id="CompilePanel.progress.finished" txt="[Selesai]"/>
<str id="CompilePanel.progress.overall" txt="Perkembangan kompilasi keseluruhan:"/>
<str id="CompilePanel.error" txt="Kompilasi gagal"/>
<str id="CompilePanel.error.reconfigure" txt="Konfigurasi ulang"/>
<str id="CompilePanel.error.ignore" txt="Abaikan"/>
<str id="CompilePanel.error.abort" txt="Batalkan"/>
<str id="CompilePanel.error.seebelow" txt="Lihat dibawah untuk perintah yang gagal dan keluarannya."/>
<str id="CompilePanel.error.nofiles" txt="Kesalahan terjadi saat melarik arsip-arsip untuk kompilasi."/>
<str id="CompilePanel.error.compilernotfound" txt="Kompiler tidak dapat dijalankan."/>
<str id="CompilePanel.error.invalidarguments" txt="Kompiler menerima argumen-argumen yang tidak sahih."/>
<str id="CompilePanel.error.noclassfile" txt="Kompiler tidak dapat menghasilkan arsip kelas untuk arsip sumber "/>
<str id="CompilePanel.choose_compiler" txt="Kompiler yang digunakan:"/>
<str id="CompilePanel.additional_arguments" txt="Argumen-argumen tambahan kompiler:"/>
<str id="ProcessPanel.heading" txt="Pemrosesan"/>
<!-- Strings for the summary of panels - START -->
<str id="SummaryPanel.info"
txt="Siap untuk pemasangan. Daftar data yang penting terdapat di bawah. Tekan &quot;Berikut&quot; untuk memulai pemasangan."/>
<str id="SummaryPanel.next" txt="Berikut"/>
<str id="TargetPanel.summaryCaption" txt="Lokasi pemasangan"/>
<str id="JDKPathPanel.summaryCaption" txt="Lokasi JDK"/>
<str id="PacksPanel.summaryCaption" txt="Paket-paket pemasangan yang dipilih"/>
<str id="ImgPacksPanel.summaryCaption" txt="Paket-paket pemasangan yang dipilih"/>
<str id="TreePacksPanel.summaryCaption" txt="Paket-paket pemasangan yang dipilih"/>
<str id="UserPathPanel.summaryCaption" txt="Lokasi Terpilih"/>
<!-- Strings for the summary of panels - END -->
<!-- Strings for the Registry -->
<str id="functionFailed.RegOpenKeyEx" txt="Tidak dapat membuka kunci registri {0}\\{1}"/>
<!-- Add your own panels specific strings here if you need or use a custom
langpack with the same syntax referred as resource CustomLangpack.xml_[ISO3]"
-->
<str id="nextmedia.title" txt="Media pemasangan berikutnya"/>
<str id="nextmedia.msg" txt="Pilih media pemasangan berikutnya."/>
<str id="nextmedia.browsebtn" txt="Jelajah"/>
<str id="nextmedia.okbtn" txt="Terapkan"/>
<str id="nextmedia.cancelbtn" txt="Batal"/>
<str id="nextmedia.choosertitle" txt="Pilih media pemasangan"/>
<str id="nextmedia.filedesc" txt="pak pemasangan (.pak*)"/>
<!-- Strings for the logging/reporting system (Messenger) -->
<!-- This string defines the time stamp format in the installation report.
The format details are documented in java.text.SimpleDateFormat -->
<str id="log.timeStamp" txt="dd-MM-yyyy [HH:mm:ss] zzzz"/>
<!-- Strings for various purposes in the logging/reporting system -->
<str id="log.reportHeading" txt=" LAPORAN PEMASANGAN IzPack"/>
<str id="log.installFailed" txt="PERINGATAN!!! Pemasangan tidak berhasil!"/>
<str id="log.partialInstall" txt="PERINGATAN!!! Pemasangan bisa jadi telah tidak selesai dengan sukses!"/>
<str id="log.messageCount" txt="Laporan ini mengandung {0} pesan umum, {1} peringatan and {2} kesalahan(s)"/>
<str id="log.application" txt="Laporan pemasangan untuk : {0} Versi {1}"/>
<str id="log.timePrefix" txt="Waktu pemasangan : {0}"/>
<str id="log.pathPrefix" txt="Direktori pemasangan : {0}"/>
<str id="log.messageHeading" txt=" --- Pesan-Pesan Pemasangan ---"/>
<str id="log.warningHeading" txt=" --- Peringatan-Peringatan ---"/>
<str id="log.errorHeading" txt=" --- Kesalahan-Kesalahan---"/>
<str id="log.exceptionPrefix" txt=" >> Eksepsi: {0}"/>
<str id="log.messagePrefix" txt="Pesan [{0}] - "/>
<str id="log.warningPrefix" txt="Warning [{0}] - "/>
<str id="log.errorPrefix" txt="Kesalahan [{0}] - "/>
<str id="log.reportWriteErrorTitle" txt="Kesalahan dalam penulisan laporan"/>
<str id="log.reportWriteError" txt="Tidak dapat menulis laporan pemasangan ke ''{0}''"/>
<str id="log.informUserTitle" txt="Masalah-Masalah Pemasangan"/>
<str id="log.saveLogTitle" txt="Simpan Berkas Catatan"/>
<str id="log.LogFileName" txt="catatanPemasangan.txt"/>
<str id="log.informUserFail"
txt="&lt;html&gt;Pemasangan tidak berhasil!&lt;br&gt;Apakah Anda ingin menulis suatu berkas catatan?&lt;/html&gt;"/>
<str id="log.informUserPartial"
txt="&lt;html&gt;Pemasangan bisa jadi telah tidak selesai dengan sukses!&lt;br&gt;Apakah Anda ingin menulis suatu berkas catatan?&lt;/html&gt;"/>
<!-- Strings for individual messages in the logging/reporting system.
Numbers for each category (message/warning/error) start at 0 -->
<str id="log.message_" txt=""/>
<str id="log.warning_" txt=""/>
<str id="log.error_0" txt="tidak dapat menulis ''{0}''"/>
<str id="InstallationGroupPanel.colNameSelected" txt="Terpilih"/>
<str id="InstallationGroupPanel.colNameInstallType" txt="JenisPemasangan"/>
<str id="InstallationGroupPanel.colNameSize" txt="Ukuran"/>
<str id="debug.changevariable" txt="ubah nilai"/>
</izpack:langpack>

View File

@ -0,0 +1,279 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<!-- The Brazilian Portuguese langpack -->
<izpack:langpack version="5.0"
xmlns:izpack="http://izpack.org/schema/langpack"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://izpack.org/schema/langpack http://izpack.org/schema/5.0/izpack-langpack-5.0.xsd">
<!-- Heading messages START -->
<str id="CheckedHelloPanel.headline" txt="Bem vindo"/>
<str id="CompilePanel.headline" txt="Compilar códigos Java"/>
<str id="ConditionalUserInputPanel.headline" txt="Dados do usuário"/>
<str id="FinishPanel.headline" txt="Instalação terminada"/>
<str id="HelloPanel.headline" txt="Bem vindo"/>
<str id="HTMLInfoPanel.headline" txt="Informações"/>
<str id="HTMLLicencePanel.headline" txt="Acordo de licença"/>
<str id="PDFLicencePanel.headline" txt="Acordo de licença"/>
<str id="ImgPacksPanel.headline" txt="Selecione pacotes de instalação"/>
<str id="InfoPanel.headline" txt="Informações"/>
<str id="InstallPanel.headline" txt="Instalação"/>
<str id="JDKPathPanel.headline" txt="Caminho do JDK"/>
<str id="LicencePanel.headline" txt="Acordo de licença"/>
<str id="PacksPanel.headline" txt="Selecione pacotes de instalação"/>
<str id="ProcessPanel.headline" txt="Executar processos externos"/>
<str id="ShortcutPanel.headline" txt="Atalhos"/>
<str id="SimpleFinishPanel.headline" txt="Instalação terminada"/>
<str id="SummaryPanel.headline" txt="Resumo dos dados do usuário"/>
<str id="TargetPanel.headline" txt="Caminho de destino"/>
<str id="TreePacksPanel.headline" txt="Selecione pacotes de instalação"/>
<str id="UserInputPanel.headline" txt="Dados do usuário"/>
<!-- General installer strings -->
<str id="installer.title" txt="IzPack - Instalação de "/>
<str id="installer.next" txt="Próximo"/>
<str id="installer.prev" txt="Anterior"/>
<str id="installer.quit" txt="Sair"/>
<str id="installer.madewith" txt="(Criado com IzPack - http://izpack.org/)"/>
<str id="installer.quit.title" txt="Tem certeza de que deseja sair ?"/>
<str id="installer.quit.message" txt="Você quer cancelar a instalação?"/>
<str id="installer.warning" txt="Aviso !"/>
<str id="installer.yes" txt="Sim"/>
<str id="installer.no" txt="Não"/>
<str id="installer.cancel" txt="Cancelar"/>
<str id="installer.error" txt="Erro"/>
<str id="installer.help" txt="Ajuda"/>
<str id="installer.help.close" txt="Fechar"/>
<str id="installer.step" txt="Passo"/>
<str id="installer.of" txt="de"/>
<str id="installer.Message" txt="Mensagem"/>
<str id="installer.errorMessage" txt="Ocorreu um erro"/>
<str id="installer.close" txt="Fechar"/>
<str id="installer.showDetails" txt="Mostrar Detalhes"/>
<str id="installer.hideDetails" txt="Ocultar Detalhes"/>
<str id="installer.copy" txt="Copiar"/>
<str id="installer.sendReport" txt="Enviar Relatório"/>
<str id="installer.continueQuestion" txt="Deseja Continuar?"/>
<str id="installer.cancelled" txt="Instalação cancelada"/>
<str id="installer.started" txt="Installation started"/>
<str id="installer.platform" txt="Platform: {0}"/>
<str id="installer.version" txt="Framework: {0}"/>
<str id="installer.finished" txt="Installation finished"/>
<!-- Uninstaller specific strings -->
<str id="uninstaller.warning" txt="Isto removerá o(s) aplicativo(s) instalado(s) !"/>
<str id="uninstaller.destroytarget" txt=" Forçar a remoção de "/>
<str id="uninstaller.uninstall" txt="Desinstalar"/>
<!-- The strings for the 'official' IzPack plugins -->
<str id="HelloPanel.welcome1" txt="Bem vindo à instalação de "/>
<str id="HelloPanel.welcome2" txt=" !"/>
<str id="HelloPanel.authors" txt="Este programa foi desenvolvido por : "/>
<str id="HelloPanel.url" txt="A página do programa é : "/>
<str id="PrinterSelectPanel.select_printer"
txt="Selecione a impressora para utilizar na configuração inicial e teste."/>
<str id="CheckedHelloPanel.productAlreadyExist0" txt="Este produto já se encontra instalado neste computador em "/>
<str id="CheckedHelloPanel.productAlreadyExist1" txt=" . Você tem certeza de que quer instalar outra cópia?"/>
<str id="CheckedHelloPanel.infoOverUninstallKey" txt="A chave de desinstalação será chamada: "/>
<!-- ConsolePrompt strings -->
<str id="ConsolePrompt.okCancel" txt="Pressione O (Ok), (C) Cancelar: "/>
<str id="ConsolePrompt.yesNo" txt="Pressione (S) Sim, (N) Não: "/>
<str id="ConsolePrompt.yesNoCancel" txt="Pressione S (Sim), (N) Não ou C (Cancelar): "/>
<str id="ConsolePrompt.ok" txt="O"/>
<str id="ConsolePrompt.cancel" txt="C"/>
<str id="ConsolePrompt.yes" txt="S"/>
<str id="ConsolePrompt.no" txt="N"/>
<!-- ConsoleInstaller strings -->
<str id="ConsoleInstaller.continueQuitRedisplay"
txt="Pressione: (1) continuar, (2) sair, (3) mostrar novamente"/>
<str id="ConsoleInstaller.acceptRejectRedisplay"
txt="Pressione: (1) aceitar, (2) rejeitar, (3) mostrar novamente"/>
<str id="ConsoleInstaller.redisplayQuit" txt="Pressione: (1) mostrar novamente, (2) sair"/>
<str id="ConsoleInstaller.permissionError"
txt="Previlégios administrativos necessário. Por favor reexecute o instalador com previlégios administrativos."/>
<str id="ConsoleInstaller.inputSelection" txt="Selecione: "/>
<str id="ConsoleInstaller.pagingMore" txt="Mais"/>
<str id="ConsoleInstaller.aborted.PressedCTRL-C" txt="CTRL-C pessionado"/>
<str id="ConsoleInstaller.aborted.LicenseRejected" txt="Licença rejeitada"/>
<str id="ConsoleInstaller.aborted.PressedQuit" txt="Sair pressionado"/>
<str id="ConsoleInstaller.shutdown.pendingFileOperations" txt="Há operações de arquivo pendentes após a reinicialização"/>
<str id="ConsoleInstaller.shutdown.rebootingNow" txt="O sistemas será reiniciando"/>
<str id="ConsoleInstaller.shutdown.done" txt="Instalção concluída"/>
<str id="ConsoleInstaller.shutdown.aborted" txt="Instalação abortada!"/>
<str id="ConsoleInstaller.shutdown.failed" txt="Instalação falhou!"/>
<str id="LicencePanel.info" txt="Por favor, leia o seguinte contrato de licença :"/>
<str id="LicencePanel.agree" txt="Eu concordo com este contrato de licença."/>
<str id="LicencePanel.notagree" txt="Eu não concordo com este contrato de licença."/>
<str id="LicencePanel.yes" txt="Sim"/>
<str id="LicencePanel.no" txt="Não"/>
<str id="InfoPanel.info" txt="Por favor, leia a seguinte informação :"/>
<str id="PathInputPanel.required" txt="O diretório escolhido deve existir."/>
<str id="PathInputPanel.notValid" txt="O diretório escolhido não contém o produto requerido."/>
<str id="TargetPanel.info" txt="Selecione o caminho para instalação :"/>
<str id="TargetPanel.browse" txt="Procurar ..."/>
<str id="TargetPanel.warn"
txt="O diretório já existe ! Tem certeza de que quer instalar neste diretório e possivelmente sobrescrever arquivos existentes?"/>
<str id="TargetPanel.empty_target"
txt="Você não especificou um local! Isto está correto?"/>
<str id="TargetPanel.createdir" txt="O diretório especificado será criado :"/>
<str id="TargetPanel.nodir"
txt="Este arquivo não é um diretório! Por favor, selecione um diretório!"/>
<str id="TargetPanel.notwritable"
txt="Este diretório não pode ser escrito! Por favor, escolha outro diretório!"/>
<str id="JDKPathPanel.extendedIntro"
txt="O programa instalado necessita um JDK com versão entre ${JDKPathPanel.minVersion} e ${JDKPathPanel.maxVersion}. Um &quot;Java Runtime Environment&quot; (JRE) não é suficiente."/>
<str id="JDKPathPanel.intro"
txt="O programa instalado necessita um JDK. Um &quot;Java Runtime Environment&quot; (JRE) não é suficiente."/>
<str id="JDKPathPanel.info" txt="Selecione o caminho do JDK:"/>
<str id="JDKPathPanel.badVersion1" txt="O JDK escolhido tem versão não recomendada (Disponível: "/>
<str id="JDKPathPanel.badVersion2" txt=" Necessário: "/>
<str id="JDKPathPanel.badVersion3" txt="). Usar esse JDK mesmo assim?"/>
<str id="PacksPanel.info" txt="Selecione os pacotes que deseja instalar :"/>
<str id="PacksPanel.tip" txt="Nota: pacotes cinzas são requeridos."/>
<str id="PacksPanel.space" txt="Espaço total requerido: "/>
<str id="PacksPanel.freespace" txt="Espaço disponível: "/>
<str id="PacksPanel.description" txt="Descrição"/>
<str id="PacksPanel.dependencyList"
txt="O pacote escolhido tem as seguintes dependências e/ou exclui"/>
<str id="PacksPanel.dependencies" txt="Dependências: "/>
<str id="PacksPanel.excludes" txt="Exclui: "/>
<str id="ImgPacksPanel.dependencyList" txt="Dependências e/ou exclui"/>
<str id="PacksPanel.notEnoughSpace"
txt="O espaço em disco requerido para a instalação é maior que o espaço em disco disponível."/>
<str id="PacksPanel.notAscertainable" txt="não dedutível"/>
<str id="InstallPanel.info" txt="Clique 'Instalar !' para iniciar o processo de instalação"/>
<str id="InstallPanel.install" txt="Instalar !"/>
<str id="InstallPanel.tip" txt="Progresso da instalação :"/>
<str id="InstallPanel.begin" txt="[Nada]"/>
<str id="InstallPanel.finished" txt="[Terminado]"/>
<str id="InstallPanel.progress" txt="Progresso total da instalação:"/>
<str id="InstallPanel.overwrite.title" txt="O arquivo já existe."/>
<str id="InstallPanel.overwrite.question" txt="O seguinte arquivo já existe. Sobrescrevê-lo?"/>
<str id="FinishPanel.success" txt="Instalação realizada com sucesso."/>
<str id="FinishPanel.done" txt="Pronto"/>
<str id="FinishPanel.fail" txt="A instalação falhou!"/>
<str id="FinishPanel.uninst.info" txt="Um programa desinstalador foi criado em:"/>
<str id="FinishPanel.auto" txt="Gerar um script para instalação automática"/>
<str id="FinishPanel.auto.tip"
txt="Utilize este script para repetir esta instalação em outros computadores."/>
<str id="ImgPacksPanel.packs" txt="Os seguintes pacotes estão disponíveis :"/>
<str id="ImgPacksPanel.snap" txt="Visualização da tela do pacote :"/>
<str id="ImgPacksPanel.checkbox" txt=" Instalar este pacote"/>
<str id="ShortcutPanel.headline" txt="Configurar atalhos"/>
<str id="ShortcutPanel.regular.list" txt="Selecione um grupo para os atalhos:"/>
<str id="ShortcutPanel.regular.default" txt="Padrão"/>
<str id="ShortcutPanel.regular.desktop" txt="Criar atalhos adicionais na Área de Trabalho"/>
<str id="ShortcutPanel.regular.startup" txt="Executar na inicialização"/>
<str id="ShortcutPanel.regular.StartMenu:Start-Menu" txt="Start-Menu"/>
<str id="ShortcutPanel.regular.StartMenu:K-Menu" txt="K-Menu"/>
<!-- "StartMenu" is a placeholder will be replaced at runtime -->
<str id="ShortcutPanel.regular.create" txt="Criar Atalhos"/>
<str id="ShortcutPanel.regular.userIntro" txt="criar atalho para:"/>
<str id="ShortcutPanel.regular.currentUser" txt="usuário atual"/>
<str id="ShortcutPanel.regular.allUsers" txt="todos usuários"/>
<str id="ShortcutPanel.alternate.apology"
txt="Desculpe, mas IzPack não pode criar atalhos neste sistema operacional. Para criar os atalhos, favor consultar o manual de seu sistema operacional."/>
<str id="ShortcutPanel.alternate.targetsLabel"
txt="Esta é a lista de executáveis aos quais o produtor deste programa lhe deu acesso."/>
<str id="ShortcutPanel.alternate.textFileExplanation"
txt="Você pode salvar informações detalhadas sobre os arquivos executáveis em um arquivo de texto para referência futura."/>
<str id="ShortcutPanel.alternate.saveButton" txt="Salvar Arquivo de Texto"/>
<str id="ShortcutPanel.textFile.header"
txt="Informação Sobre Atalhos\n====================\n\nA seguinte é uma listagem de toda informação relevante sobre os atalhos\ndesejados. Esta informação deve possibilitar a criação manual de atalhos.\n"/>
<str id="ShortcutPanel.textFile.name" txt="Atalho : "/>
<str id="ShortcutPanel.textFile.location" txt="Local Desejado : "/>
<str id="ShortcutPanel.textFile.description" txt="Descrição : "/>
<str id="ShortcutPanel.textFile.target" txt="Arquivo Executável : "/>
<str id="ShortcutPanel.textFile.command" txt="Linha de Comando : "/>
<str id="ShortcutPanel.textFile.iconName" txt="Arquivo do Ícone : "/>
<str id="ShortcutPanel.textFile.iconIndex" txt="Índice do Ícone : "/>
<str id="ShortcutPanel.textFile.work" txt="Diretório de Trabalho : "/>
<str id="ShortcutPanel.location.desktop" txt="Desktop"/>
<str id="ShortcutPanel.location.applications" txt="Menu de Aplicativos"/>
<str id="ShortcutPanel.location.startMenu" txt="Menu Iniciar"/>
<str id="ShortcutPanel.location.startup" txt="Grupo Iniciar"/>
<str id="UserInputPanel.error.caption" txt="Erro de entrada"/>
<str id="UserInputPanel.search.autodetect" txt="Autodetecção"/>
<!-- more descriptive error message would be cool, like specifying what file we looked for -->
<str id="UserInputPanel.search.autodetect.failed.message" txt="Autodetecção falhou."/>
<str id="UserInputPanel.search.autodetect.failed.caption" txt="Autodetecção falhou."/>
<str id="UserInputPanel.search.autodetect.tooltip" txt="Procure pelo arquivo ou diretório nos caminhos abaixo."/>
<str id="UserInputPanel.search.location" txt="Entre a localização de {0}."/>
<str id="UserInputPanel.search.location.checkedfile" txt="A existencia de (0) é checada."/>
<str id="UserInputPanel.search.browse" txt="Procurar..."/>
<str id="UserInputPanel.search.wrongselection.message"
txt="O arquivo ou diretório escolhido não existe ou é não é apropriado."/>
<str id="UserInputPanel.search.wrongselection.caption" txt="Seleção inválida."/>
<str id="CompilePanel.heading" txt="Compilação"/>
<str id="CompilePanel.tip" txt="Progresso do trabalho de compilação:"/>
<str id="CompilePanel.browse" txt="Procurar..."/>
<str id="CompilePanel.browse.approve" txt="Usar como compilador"/>
<str id="CompilePanel.start" txt="Iniciar"/>
<str id="CompilePanel.progress.initial" txt="[Clique no botão Iniciar para instalar]"/>
<str id="CompilePanel.progress.finished" txt="[Terminado]"/>
<str id="CompilePanel.progress.overall" txt="Progresso total da compilação:"/>
<str id="CompilePanel.error" txt="Compilação falhou"/>
<str id="CompilePanel.error.reconfigure" txt="Reconfigurar"/>
<str id="CompilePanel.error.ignore" txt="Ignorar"/>
<str id="CompilePanel.error.abort" txt="Abortar"/>
<str id="CompilePanel.error.seebelow" txt="Veja abaixo o comando que falhou e sua saída."/>
<str id="CompilePanel.error.nofiles" txt="Erro durante a busca pelo arquivos para compilação."/>
<str id="CompilePanel.error.compilernotfound" txt="O compilador não pôde ser executado."/>
<str id="CompilePanel.error.invalidarguments" txt="O compilador recusou os argumentos fornecidos."/>
<str id="CompilePanel.error.noclassfile" txt="O compilador não gerou um arquivo class para o código fonte "/>
<str id="CompilePanel.choose_compiler" txt="Compilador a ser usado:"/>
<str id="CompilePanel.additional_arguments" txt="Argumentos adicionais do compilador:"/>
<str id="ProcessPanel.heading" txt="Processando"/>
<!-- Strings for the summary of panels - START -->
<str id="SummaryPanel.info"
txt="Pronto para instalar. Os dados importantes são listados abaixo. Clique &quot;Próximo&quot; para iniciar a instalação, "/>
<str id="SummaryPanel.next" txt="Proximo"/>
<str id="TargetPanel.summaryCaption" txt="Caminho da instalação"/>
<str id="JDKPathPanel.summaryCaption" txt="Caminho do JDK"/>
<str id="PacksPanel.summaryCaption" txt="Pacotes de instalação escolhidos"/>
<str id="ImgPacksPanel.summaryCaption" txt="Pacotes de instalação escolhidos"/>
<str id="TreePacksPanel.summaryCaption" txt="Pacotes de instalação escolhidos"/>
<!-- Strings for the summary of panels - END -->
<!-- Strings for the Registry -->
<str id="functionFailed.RegOpenKeyEx" txt="Não foi possível abrir a chave do registro {0}\\{1}."/>
<!-- Add your own panels specific strings here if you need or use a custom
langpack with the same syntax referred as resoure CustomLangpack.xml_[ISO3]"
-->
<str id="nextmedia.title" txt="Próxima mídia de instalação"/>
<str id="nextmedia.msg" txt="Escolha a próxima mídia de instalação."/>
<str id="nextmedia.browsebtn" txt="Explorar"/>
<str id="nextmedia.okbtn" txt="Aplicar"/>
<str id="nextmedia.cancelbtn" txt="Cancelar"/>
<str id="nextmedia.choosertitle" txt="Escolha a mídia de instalação"/>
<str id="nextmedia.filedesc" txt="pacotes de instalação (.pak*)"/>
</izpack:langpack>

View File

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="GB2312" standalone="yes" ?>
<!-- The Simplified Chinese langpack -->
<izpack:langpack version="5.0"
xmlns:izpack="http://izpack.org/schema/langpack"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://izpack.org/schema/langpack http://izpack.org/schema/5.0/izpack-langpack-5.0.xsd">
<!-- ConsolePrompt strings -->
<str id="ConsolePrompt.okCancel" txt="Enter O for OK, C to Cancel: "/>
<str id="ConsolePrompt.yesNo" txt="Enter Y for Yes, N for No: "/>
<str id="ConsolePrompt.yesNoCancel" txt="Enter Y for Yes, N for No, or C to Cancel: "/>
<str id="ConsolePrompt.ok" txt="O"/>
<str id="ConsolePrompt.cancel" txt="C"/>
<str id="ConsolePrompt.yes" txt="Y"/>
<str id="ConsolePrompt.no" txt="N"/>
<!-- ConsoleInstaller strings -->
<str id="ConsoleInstaller.continueQuitRedisplay" txt="Press 1 to continue, 2 to quit, 3 to redisplay"/>
<str id="ConsoleInstaller.acceptRejectRedisplay" txt="Press 1 to accept, 2 to reject, 3 to redisplay"/>
<str id="ConsoleInstaller.redisplayQuit" txt="Press 1 to redisplay, 2 to quit"/>
<str id="ConsoleInstaller.permissionError" txt="Administrative privileges required. Please re-run the installer with administrative privileges."/>
<str id="ConsoleInstaller.inputSelection" txt="Input selection: "/>
<str id="ConsoleInstaller.pagingMore" txt="More"/>
<str id="ConsoleInstaller.aborted.PressedCTRL-C" txt="CTRL-C pressed"/>
<str id="ConsoleInstaller.aborted.LicenseRejected" txt="License rejected"/>
<str id="ConsoleInstaller.aborted.PressedQuit" txt="Quit pressed"/>
<str id="ConsoleInstaller.shutdown.pendingFileOperations" txt="There are file operations pending after reboot"/>
<str id="ConsoleInstaller.shutdown.rebootingNow" txt="Rebooting now automatically"/>
<str id="ConsoleInstaller.shutdown.done" txt="Console installation done"/>
<str id="ConsoleInstaller.shutdown.aborted" txt="Console installation ABORTED by the user!"/>
<str id="ConsoleInstaller.shutdown.failed" txt="Console installation FAILED!"/>
<!-- General installer strings -->
<str id="installer.title" txt="IzPack - <20><>װ "/>
<str id="installer.next" txt="<22><>һ<EFBFBD><D2BB>"/>
<str id="installer.prev" txt="<22><>һ<EFBFBD><D2BB>"/>
<str id="installer.quit" txt="<22>˳<EFBFBD>"/>
<str id="installer.madewith" txt="(<28><>IzPack<63><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - http://izpack.org/)"/>
<str id="installer.quit.title" txt="<22>Ƿ<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>˳<EFBFBD>?"/>
<str id="installer.quit.message" txt="<22><>ȡ<EFBFBD><C8A1><EFBFBD>ð<EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD> !"/>
<str id="installer.warning" txt="<22><><EFBFBD><EFBFBD> !"/>
<str id="installer.yes" txt="<22><>"/>
<str id="installer.no" txt="<22><>"/>
<str id="installer.cancel" txt=<><C8A1>"/>
<str id="installer.error" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="installer.errorMessage" txt="An error occured"/>
<str id="installer.close" txt="Close"/>
<str id="installer.showDetails" txt="Show Details"/>
<str id="installer.hideDetails" txt="Hide Details"/>
<str id="installer.copy" txt="Copy"/>
<str id="installer.sendReport" txt="Send Report"/>
<str id="installer.continueQuestion" txt="Continue anyway?"/>
<str id="installer.cancelled" txt="Installation cancelled"/>
<str id="installer.started" txt="Installation started"/>
<str id="installer.platform" txt="Platform: {0}"/>
<str id="installer.version" txt="Framework: {0}"/>
<str id="installer.finished" txt="Installation finished"/>
<!-- Uninstaller specific strings -->
<str id="uninstaller.warning" txt="<22><>ж<EFBFBD><D0B6><EFBFBD>Ѱ<EFBFBD>װ<EFBFBD><D7B0>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD> !"/>
<str id="uninstaller.destroytarget" txt=" ǿ<><C7BF>ɾ<EFBFBD><C9BE> "/>
<str id="uninstaller.uninstall" txt=<><D0B6>"/>
<!-- The strings for the 'official' IzPack plugins -->
<str id="HelloPanel.welcome1" txt="<22><>ӭ<EFBFBD><D3AD>װ"/>
<str id="HelloPanel.welcome2" txt=" !"/>
<str id="HelloPanel.authors" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : "/>
<str id="HelloPanel.url" txt="<22><>ҳ : "/>
<str id="LicencePanel.info" txt="<22><><EFBFBD><EFBFBD>ϸ<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>:"/>
<str id="LicencePanel.agree" txt="<22>ҽ<EFBFBD><D2BD>ܸ<EFBFBD><DCB8><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."/>
<str id="LicencePanel.notagree" txt="<22>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ܸ<EFBFBD><DCB8><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."/>
<str id="LicencePanel.yes" txt="<22><>"/>
<str id="LicencePanel.no" txt="<22><>"/>
<str id="InfoPanel.info" txt="<22><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ :"/>
<str id="TargetPanel.info" txt="ѡ<><D1A1><EFBFBD><EFBFBD>װ·<D7B0><C2B7> :"/>
<str id="TargetPanel.browse" txt="<22><><EFBFBD><EFBFBD> ..."/>
<str id="TargetPanel.warn"
txt="Ŀ¼<C4BF>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD> ! <20><><EFBFBD>ܸ<EFBFBD><DCB8><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Ƿ<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>ڴ˰<DAB4>װ?"/>
<str id="TargetPanel.empty_target"
txt="<22><>û<EFBFBD><C3BB>ָ<EFBFBD><D6B8>Ŀ<EFBFBD><C4BF>·<EFBFBD><C2B7>! <20>Ƿ<EFBFBD><C7B7><EFBFBD>ȷ?"/>
<str id="TargetPanel.createdir" txt="Ŀ<><C4BF>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :"/>
<str id="TargetPanel.nodir"
txt="<22><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ŀ¼! <20><>ѡ<EFBFBD><D1A1>һ<EFBFBD><D2BB>Ŀ¼!"/>
<str id="TargetPanel.notwritable"
txt="Ŀ¼<C4BF>޷<EFBFBD>д<EFBFBD><D0B4>! <20><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼!"/>
<str id="PacksPanel.info" txt="ѡ<><D1A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>װ<EFBFBD>İ<EFBFBD> :"/>
<str id="PacksPanel.tip" txt=<><D7A2>: <20><>ɫѡ<C9AB><D1A1><EFBFBD>DZ<EFBFBD>ѡ<EFBFBD><D1A1>."/>
<str id="PacksPanel.space" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>: "/>
<str id="PacksPanel.freespace" txt="<22><>Ч<EFBFBD>ռ<EFBFBD>: "/>
<str id="PacksPanel.description" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="PacksPanel.dependencyList" txt="<22><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>װ<EFBFBD><D7B0><EFBFBD>°<EFBFBD>"/>
<str id="ImgPacksPanel.dependencyList" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="PacksPanel.notEnoughSpace" txt="<22><>װҪ<D7B0><D2AA><EFBFBD>Ĵ<EFBFBD><C4B4>̿ռ<D5BC><E4B3AC><EFBFBD>˿<EFBFBD><CBBF>õĴ<C3B5><C4B4>̿ռ<CCBF>."/>
<str id="PacksPanel.notAscertainable" txt="not ascertainable"/>
<str id="InstallPanel.info" txt="<22><><EFBFBD><EFBFBD> '<27><>װ !' <20><>ʼ<EFBFBD><CABC>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>"/>
<str id="InstallPanel.install" txt="<22><>װ !"/>
<str id="InstallPanel.tip" txt="<22><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD> :"/>
<str id="InstallPanel.begin" txt="[Nothing]"/>
<str id="InstallPanel.finished" txt="[<5B><><EFBFBD><EFBFBD>]"/>
<str id="InstallPanel.progress" txt="Overall installation progress :"/>
<str id="InstallPanel.overwrite.title" txt="<22>ļ<EFBFBD><C4BC>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>"/>
<str id="InstallPanel.overwrite.question" txt="<22><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>. <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>?"/>
<str id="FinishPanel.success" txt="<22><>װ<EFBFBD>ɹ<EFBFBD>."/>
<str id="FinishPanel.done" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="FinishPanel.fail" txt="<22><>װʧ<D7B0><CAA7>!"/>
<str id="FinishPanel.uninst.info" txt=<>س<EFBFBD><D8B3><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"/>
<str id="FinishPanel.auto" txt="<22><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>װ<EFBFBD>ű<EFBFBD>"/>
<str id="FinishPanel.auto.tip"
txt="ʹ<>øýű<C3BD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΰ<EFBFBD>װ."/>
<str id="ImgPacksPanel.packs" txt="<22><>ǰ<EFBFBD><C7B0>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :"/>
<str id="ImgPacksPanel.snap" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :"/>
<str id="ImgPacksPanel.checkbox" txt=" <20><>װ<EFBFBD>ð<EFBFBD>"/>
<str id="ShortcutPanel.regular.list" txt="ѡ<><D1A1><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>:"/>
<str id="ShortcutPanel.regular.default" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="ShortcutPanel.regular.desktop" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4B4><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ"/>
<str id="ShortcutPanel.regular.create" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ"/>
<str id="ShortcutPanel.regular.userIntro" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ:"/>
<str id="ShortcutPanel.regular.currentUser" txt="<22><>ǰ<EFBFBD>û<EFBFBD>"/>
<str id="ShortcutPanel.regular.allUsers" txt="<22><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>"/>
<str id="ShortcutPanel.alternate.apology" txt="<22><><EFBFBD>ź<EFBFBD>IzPack<63><6B>֧<EFBFBD><D6A7><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ϵͳ<CFB5>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5>ֲ<EFBFBD>."/>
<str id="ShortcutPanel.alternate.targetsLabel"
txt="The following is a list of targets that the manufacturer of this software product wanted you to have access to."/>
<str id="ShortcutPanel.alternate.textFileExplanation" txt=<><CEAA><EFBFBD>Ժ<EFBFBD><D4BA>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>԰<EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>ļ<EFBFBD>."/>
<str id="ShortcutPanel.alternate.saveButton" txt="<22><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>ļ<EFBFBD>"/>
<str id="ShortcutPanel.textFile.header"
txt="<22><><EFBFBD>ݷ<EFBFBD>ʽ<EFBFBD><CABD>Ϣ\n====================\n\nThe following is a listing of all relevant information about the intended\nshortcuts. <20><><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>ʽ<EFBFBD><CABD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>.\n"/>
<str id="ShortcutPanel.textFile.name" txt="<22><><EFBFBD>ݷ<EFBFBD>ʽ : "/>
<str id="ShortcutPanel.textFile.location" txt="Intended Location : "/>
<str id="ShortcutPanel.textFile.description" txt="<22><><EFBFBD><EFBFBD> : "/>
<str id="ShortcutPanel.textFile.target" txt="<22><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF> : "/>
<str id="ShortcutPanel.textFile.command" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : "/>
<str id="ShortcutPanel.textFile.iconName" txt=<><CDBC><EFBFBD>ļ<EFBFBD> : "/>
<str id="ShortcutPanel.textFile.iconIndex" txt=<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : "/>
<str id="ShortcutPanel.textFile.work" txt="<22><><EFBFBD><EFBFBD>Ŀ¼ : "/>
<str id="ShortcutPanel.location.desktop" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="ShortcutPanel.location.applications" txt=<>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>˵<EFBFBD>"/>
<str id="ShortcutPanel.location.startMenu" txt="<22><>ʼ<EFBFBD>˵<EFBFBD>"/>
<str id="ShortcutPanel.location.startup" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/>
<str id="UserInputPanel.error.caption" txt=<><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/>
<str id="UserInputPanel.search.autodetect" txt="<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>"/>
<!-- more descriptive error message would be cool, like specifying what file we looked for -->
<str id="UserInputPanel.search.autodetect.failed.message" txt="<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>."/>
<str id="UserInputPanel.search.autodetect.failed.caption" txt="<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>."/>
<str id="UserInputPanel.search.autodetect.tooltip" txt="<22>ڸ<EFBFBD><DAB8><EFBFBD>·<EFBFBD><C2B7><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ŀ¼."/>
<str id="UserInputPanel.search.location" txt="<22><><EFBFBD><EFBFBD>{0}<7D><>·<EFBFBD><C2B7>."/>
<str id="UserInputPanel.search.location.checkedfile" txt="The existence of {0} is checked."/>
<str id="UserInputPanel.search.browse" txt="<22><><EFBFBD><EFBFBD>..."/>
<str id="UserInputPanel.search.wrongselection.message" txt="<22><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB>߲<EFBFBD><DFB2><EFBFBD>ȷ."/>
<str id="UserInputPanel.search.wrongselection.caption" txt="<22><>Чѡ<D0A7><D1A1>."/>
<str id="CompilePanel.heading" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="CompilePanel.tip" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"/>
<str id="CompilePanel.browse" txt="<22><><EFBFBD><EFBFBD>..."/>
<str id="CompilePanel.browse.approve" txt="<22><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>"/>
<str id="CompilePanel.start" txt="<22><>ʼ"/>
<str id="CompilePanel.progress.initial" txt="[<5B><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ť]"/>
<str id="CompilePanel.progress.finished" txt="[<5B><><EFBFBD><EFBFBD>]"/>
<str id="CompilePanel.progress.overall" txt="Overall compilation progress:"/>
<str id="CompilePanel.error" txt="<22><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>"/>
<str id="CompilePanel.error.reconfigure" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/>
<str id="CompilePanel.error.ignore" txt="<22><><EFBFBD><EFBFBD>"/>
<str id="CompilePanel.error.abort" txt="<22><>ֹ"/>
<str id="CompilePanel.error.seebelow" txt="<22><><EFBFBD>²鿴<C2B2><E9BFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."/>
<str id="CompilePanel.error.nofiles" txt="<22><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>."/>
<str id="CompilePanel.error.compilernotfound" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."/>
<str id="CompilePanel.error.invalidarguments" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><DCB4><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>."/>
<str id="CompilePanel.error.noclassfile" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ΪԴ<CEAA><D4B4><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD> "/>
<str id="CompilePanel.choose_compiler" txt="ʹ<>õı<C3B5><C4B1><EFBFBD><EFBFBD><EFBFBD>:"/>
<str id="CompilePanel.additional_arguments" txt="<22><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"/>
<str id="ProcessPanel.heading" txt="<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/>
<!-- Add your own panels specific strings here if you need -->
</izpack:langpack>

View File

@ -40,6 +40,8 @@
in override.properties to ensure that Android will build correcly; fix any issues.
Ensure that JAVA_HOME is unset.
- Verify CI is passing on both Gitlab and Github
## A day or two before
@ -67,6 +69,8 @@
5. Update and check in blocklist-tor.txt with `maketorblocklist.sh`
6. Verify CI is passing on both Gitlab and Github
## On release day

View File

@ -0,0 +1,449 @@
package net.i2p.util;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import net.i2p.I2PAppContext;
import net.i2p.util.ObjectCounterUnsafe;
/**
* Output translation stats by loading ResourceBundles from jars and wars,
* in html or text format.
*
* Bundles only, does not support external resources (html files, man pages,
* Debian po files) or the gettext properties files.
*
* This is run at build time, so output is not tagged or translated.
*
* @since 0.9.64
*/
public class TranslationStatus {
private final I2PAppContext _context;
private final boolean _html;
private final StringBuilder buf, buf2;
private final List<String> langs;
private final Set<Locale> foundLangs;
private final ObjectCounterUnsafe<Locale> counts;
private final ObjectCounterUnsafe<Locale> bundles;
private static final String[] JARS = { "desktopgui.jar", "i2p.jar",
"i2psnark.war", "i2ptunnel.jar", "i2ptunnel.war",
"mstreaming.jar", "router.jar", "routerconsole.jar",
"susidns.war", "susimail.war" };
// Java lang codes, see notes below
private static final String[] LANGS = { "ar", "az", "bg", "ca", "cs", "da", "de", "el", "es", "es_AR",
"et", "fa", "fi", "fr", "gl", "hi", "hr", "hu", "in", "it", "iw",
"ja", "ko", "ku", "mg", "nb", "nl", "nn", "pl", "pt", "pt_BR",
"ro", "ru", "sk", "sl", "sq", "sr", "sv", "tk", "tr", "uk", "vi",
"zh", "zh_TW" };
private static final String[] FILES = {
"core/java/src/gnu/getopt/MessagesBundle.properties",
"apps/routerconsole/resources/docs/readme.html", // no country variants supported
"installer/resources/eepsite/docroot/help/index.html",
"installer/resources/locale-man/man.po", // non-Java
"installer/resources/locale/po/messages.po", // non-Java
"debian/po/.po" }; // non-Java
public TranslationStatus(I2PAppContext ctx, boolean html) {
_context = ctx;
_html = html;
buf = new StringBuilder(65536);
buf2 = new StringBuilder(4096);
langs = Arrays.asList(LANGS);
counts = new ObjectCounterUnsafe<Locale>();
bundles = new ObjectCounterUnsafe<Locale>();
foundLangs = new HashSet<Locale>(64);
}
/*
only useful if we bundle this at runtime
public String getStatus() throws IOException {
File base = _context.getBaseDir();
File jars = new File(base, "lib");
File wars = new File(base, "webapps");
File[] files = new File[JARS.length];
for (int i = 0; i < JARS.length; i++) {
String f = JARS[i];
files[i] = new File(f.endsWith(".jar") ? jars : wars, f);
}
return getStatus(files);
}
*/
public String getStatus(File[] files) throws IOException {
buf.setLength(0);
buf2.setLength(0);
List<String> classes = new ArrayList<String>(64);
int grandtot = 0;
int resources = 0;
// pass 1: for each file
for (int i = 0; i < files.length; i++) {
// pass 1A: collect the class names in the file
ZipFile zip = null;
try {
zip = new ZipFile(files[i]);
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
if (name.contains("messages_") && !name.contains("$")) {
if (name.startsWith("WEB-INF/classes/"))
name = name.substring(16);
classes.add(name);
}
}
Collections.sort(classes);
} catch (IOException ioe) {
ioe.printStackTrace();
continue;
} finally {
if (zip != null) try { zip.close(); } catch (IOException e) {}
}
if (classes.isEmpty()) {
System.err.println("No translations found in " + files[i]);
continue;
}
// pass 1B: setup a classloader, load each class, calculate max strings
// note that to be accurate this requires, for each resource, at least one translation to be at 100%
// this is mostly true or close enough. To do it right would require parsing the English po file,
// since we don't compile it.
URL url;
if (files[i].getName().endsWith(".jar")) {
url = files[i].toURI().toURL();
} else if (files[i].getName().endsWith(".war")) {
try {
url = (new URI("jar:file:" + files[i] + "!/WEB-INF/classes/")).toURL();
} catch (URISyntaxException use) { continue; }
} else {
System.err.println("Not a jar/war file: " + files[i]);
continue;
}
URL[] urls = new URL[] { url };
URLClassLoader cl = new URLClassLoader(urls);
String pclz = "";
int max = 0;
List<ResourceBundle> buns = new ArrayList<ResourceBundle>(64);
for (String name : classes) {
name = name.substring(0, name.length() - 6); // .class
int c = name.indexOf('_');
String clz = name.substring(0, c).replace("/", ".");
if (!clz.equals(pclz)) {
// pass 1C: output a table for the resource
// output goes here, we have to make two passes to find the max
// number of entries to generate a true %
if (!buns.isEmpty()) {
report(pclz, max, buns);
resources++;
}
grandtot += max;
pclz = clz;
max = 0;
buns.clear();
}
String s = name.substring(c + 1);
String lang;
String country;
Locale loc;
c = s.indexOf("_");
if (c < 0) {
lang = s;
country = null;
loc = new Locale(lang);
} else {
lang = s.substring(0, c);
country = s.substring(c + 1);
loc = new Locale(lang, country);
}
foundLangs.add(loc);
ResourceBundle bun;
try {
bun = ResourceBundle.getBundle(clz, loc, cl);
} catch (Exception e) {
System.err.println("FAILED loading class " + clz + " lang " + lang + " country " + country);
continue;
}
// in this pass we just calculate the max strings
buns.add(bun);
Set<String> keys = bun.keySet();
int tot = keys.size() - 1; // exclude header
if (tot > max)
max = tot;
}
if (!buns.isEmpty()) {
report(pclz, max, buns);
grandtot += max;
resources++;
}
classes.clear();
}
nl();
// pass 2: resources not in jars/wars
resources += nonCompiledStatus();
nl();
// pass 3: output summary table
// from here down to buf2 so we can output it first
String h = "Translation Summary (" + resources + " resources, " + langs.size() + " languages, " + grandtot + " strings)";
if (_html) {
buf2.append("<h2>" + h + "</h2>\n");
buf2.append("<p>Note: % translated includes compiled resources only</p>\n");
} else {
buf2.append(h);
buf2.append("\n\nNote: % translated includes compiled resources only\n\n");
}
if (_html) {
buf2.append("<table class=\"debug_tx_total\"><tr><th>Language<th>Language Code<th>% Translated<th>Missing Resources\n");
} else {
buf2.append("Code\t %TX\tMissing\tLanguage");
nl2();
buf2.append("----\t------\t--------\t-------");
nl2();
}
List<Locale> sorted = counts.sortedObjects();
for (Locale loc : sorted) {
String s = loc.getLanguage();
String lang = loc.getDisplayLanguage();
String country = loc.getCountry();
if (country.length() > 0) {
s += '_' + country;
country = '(' + loc.getDisplayCountry() + ')';
}
if (_html)
buf2.append(String.format(Locale.US, "<tr><td>%s %s<td>%s<td>%5.1f%%<td>%d\n", lang, country, s, 100f * counts.count(loc) / grandtot, resources - bundles.count(loc)));
else
buf2.append(String.format("%s\t%5.1f%%\t%s %s\n", s, 100f * counts.count(loc) / grandtot, resources - bundles.count(loc), lang, country));
}
if (_html)
buf2.append("</table>");
nl2();
nl2();
if (_html)
buf2.append("<h2>Compiled Resources</h2>\n");
else
buf2.append("Compiled Resources\n\n");
String rv = buf2.toString() + buf.toString();
buf.setLength(0);
buf2.setLength(0);
return rv;
}
private void report(String clz, int max, List<ResourceBundle> buns) {
nl();
if (clz.endsWith(".messages"))
clz = clz.substring(0, clz.length() - 9);
if (_html)
buf.append("<h3>Translations for " + clz + " (" + max + " strings, " + buns.size() + " translations)</h3>");
else
buf.append("\nTranslations for " + clz + " (" + max + " strings, " + buns.size() + " translations)\n");
nl();
if (_html) {
buf.append("<table class=\"debug_tx_resource\"><tr><th>Language <th>Language Code<th>Translated<th>% Translated");
} else {
buf.append("Code\t TX\t %TX\tLanguage");
nl();
buf.append("----\t----\t------\t--------");
nl();
}
Set<String> missing = new TreeSet<String>(langs);
for (ResourceBundle bun : buns) {
//int not = 0;
//int same = 0;
//int tx = 0;
Set<String> keys = bun.keySet();
int tot = Math.max(0, keys.size() - 1); // exclude header
/*
for (String k : keys) {
try {
String v = bun.getString(k);
if (v.length() == 0)
not++;
else if (v.equals(k))
same++;
else
tx++;
} catch (MissingResourceException e) {
not++;
}
}
*/
Locale loc = bun.getLocale();
String lang = loc.getLanguage();
String country = loc.getCountry();
String dlang = loc.getDisplayLanguage();
if (country.length() > 0) {
lang += '_' + country;
country = '(' + loc.getDisplayCountry() + ')';
}
missing.remove(lang);
counts.add(loc, tot);
bundles.increment(loc);
if (_html)
buf.append(String.format(Locale.US, "<tr><td>%s %s<td>%s<td>%4d<td>%5.1f%%\n", dlang, country, lang, tot, 100f * tot / max));
else
buf.append(String.format("%s\t%4d\t%5.1f%%\t%s %s\n", lang, tot, 100f * tot / max, dlang, country));
}
if (!missing.isEmpty()) {
if (_html)
buf.append("<tr><td class=\"debug_tx_center\" colspan=\"4\"><b>Not Translated</b>\n");
else
buf.append("Not translated:\n");
for (String s : missing) {
String lang;
String country;
Locale loc;
int c = s.indexOf("_");
if (c < 0) {
lang = s;
country = "";
loc = new Locale(lang);
} else {
lang = s.substring(0, c);
country = s.substring(c + 1);
loc = new Locale(lang, country);
country = " (" + loc.getDisplayCountry() + ')';
}
String dlang = loc.getDisplayLanguage();
if (_html)
buf.append("<tr><td>").append(dlang).append(country).append("<td>").append(s).append("<td>--<td>--\n");
else
buf.append(s).append("\t--\t--\t").append(dlang).append(country).append('\n');
}
}
if (_html)
buf.append("</table>");
nl();
}
private int nonCompiledStatus() {
int rv = 0;
if (_html) {
buf.append("<h2>Other Resources</h2>\n");
} else {
buf.append("\nOther Resources\n\n");
}
for (String file : FILES) {
boolean nonJava = file.startsWith("debian/po/") ||
file.startsWith("installer/resources/locale-man/") ||
file.startsWith("installer/resources/locale/po/");
boolean noCountries = file.startsWith("apps/routerconsole/resources/docs/");
int dot = file.lastIndexOf(".");
int slash = file.lastIndexOf("/");
String pfx = file.substring(slash + 1, dot);
String sfx = file.substring(dot);
String sdir = file.substring(0, slash);
// we assume we're in build/
File dir = new File("..", sdir);
if (!dir.exists())
continue;
rv++;
if (_html) {
buf.append("<h3>Translations for " + file + "</h3>\n");
buf.append("<table class=\"debug_tx_file\"><tr><th>Language <th>Language Code<th>Translated?");
} else {
buf.append("\nTranslations for " + file + "\n");
buf.append("Code\tTX\tLanguage\n");
buf.append("----\t--\t--------\n");
}
for (String lg : LANGS) {
String njlg = lg;
if (nonJava) {
// non-java (debian, installer, man) undo conversion
if (lg.equals("in"))
njlg = "id";
if (lg.equals("iw"))
njlg = "he";
}
String sf;
if (pfx.length() > 0)
sf = pfx + '_' + njlg + sfx;
else
sf = njlg + sfx;
File f = new File(dir, sf);
boolean ok = f.exists();
String lang;
String country;
Locale loc;
int c = lg.indexOf("_");
if (c < 0) {
lang = lg;
country = "";
loc = new Locale(lang);
} else {
lang = lg.substring(0, c);
country = lg.substring(c + 1);
loc = new Locale(lang, country);
country = " (" + loc.getDisplayCountry() + ')';
}
String dlang = loc.getDisplayLanguage();
String sok = (noCountries && c >= 0) ? "n/a" : (ok ? (_html ? "&#x2714;" : "yes") : (_html ? "--" : "no"));
if (_html)
buf.append("<tr><td>").append(dlang).append(country).append("<td>").append(lg).append("<td>").append(sok).append("\n");
else
buf.append(lg).append('\t').append(sok).append('\t').append(dlang).append(country).append("\n");
if (ok || (noCountries && c >= 0))
bundles.increment(loc);
if (ok)
foundLangs.add(loc);
}
if (_html)
buf.append("</table>");
}
return rv;
}
private void nl() {
buf.append(_html ? "<br>\n" : "\n");
}
private void nl2() {
buf2.append(_html ? "<br>\n" : "\n");
}
public static void main(String[] args) throws IOException {
boolean html = false;
if (args.length > 0 && args[0].equals("-h")) {
html = true;
args = Arrays.copyOfRange(args, 1, args.length);
}
if (args.length == 0)
args = JARS;
File[] files = new File[args.length];
for (int i = 0; i < args.length; i++) {
String f = JARS[i];
files[i] = new File(f);
}
TranslationStatus ts = new TranslationStatus(I2PAppContext.getGlobalContext(), html);
System.out.print(ts.getStatus(files));
}
}

View File

@ -19,8 +19,8 @@ public class RouterVersion {
public final static String ID = "Git";
public final static String VERSION = CoreVersion.VERSION;
/** for example: "beta", "alpha", "rc" */
public final static String QUALIFIER = "-rc";
public final static long BUILD = 8;
public final static String QUALIFIER = "";
public final static long BUILD = 1;
/** for example "-test" */
public final static String EXTRA = "";
public final static String FULL_VERSION = VERSION + "-" + BUILD + QUALIFIER + EXTRA;