55 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 " />
66 < script src ="/iframe/assets/jszip.min.js "> </ script >
77 < script src ="/iframe/assets/pdf.min.js "> </ script >
8- < title id ="pageTitle "> </ title >
8+ < title id ="pageTitle " data-i18n =" footprint_generator " > </ title >
99 < style >
1010 body {
1111 font-family : 'Segoe UI' , Tahoma, Geneva, Verdana, sans-serif;
893893 < div id ="settings-modal " class ="settings-modal ">
894894 < div class ="settings-content " style ="width: 500px ">
895895 < div class ="settings-header ">
896- < h3 class ="settings-title " id ="settingsTitle "> </ h3 >
896+ < h3 class ="settings-title " id ="settingsTitle " data-i18n =" settings " > </ h3 >
897897 < button class ="close-btn " id ="close-settings "> ×</ button >
898898 </ div >
899899 < div class ="form-group ">
900- < label for ="provider-select " id ="labelProvider "> </ label >
900+ < label for ="provider-select " id ="labelProvider " data-i18n =" model_provider " > </ label >
901901 < select id ="provider-select ">
902- < option value ="qwen " id ="optQwen "> </ option >
903- < option value ="zhipu " id ="optZhipu "> </ option >
904- < option value ="custom " id ="optCustom "> </ option >
902+ < option value ="qwen " id ="optQwen " data-i18n =" tongyi_qianwen " > </ option >
903+ < option value ="zhipu " id ="optZhipu " data-i18n =" zhipu_ai " > </ option >
904+ < option value ="custom " id ="optCustom " data-i18n =" custom " > </ option >
905905 </ select >
906906 </ div >
907907 < div class ="form-group " id ="model-group ">
908- < label for ="model-select " id ="labelModel "> </ label >
908+ < label for ="model-select " id ="labelModel " data-i18n =" select_model " > </ label >
909909 < select id ="model-select ">
910910 < option value ="qwen3-vl-plus " selected > qwen3-vl-plus</ option >
911911 < option value ="qwen-vl-max-latest "> qwen-vl-max-latest</ option >
@@ -915,20 +915,20 @@ <h3 class="settings-title" id="settingsTitle"></h3>
915915 </ select >
916916 </ div >
917917 < div class ="form-group " id ="api-key-group ">
918- < label for ="api-key " id ="labelApiKey "> </ label >
919- < input type ="text " id ="api-key " />
918+ < label for ="api-key " id ="labelApiKey " data-i18n =" api_key " > </ label >
919+ < input type ="text " id ="api-key " data-i18n-placeholder =" enter_api_key " />
920920 </ div >
921921 < div class ="form-group " id ="api-url-group " style ="display: none ">
922- < label for ="api-url " id ="labelApiUrl "> </ label >
923- < input type ="text " id ="api-url " />
922+ < label for ="api-url " id ="labelApiUrl " data-i18n =" api_url " > </ label >
923+ < input type ="text " id ="api-url " data-i18n-placeholder =" enter_api_url " />
924924 </ div >
925925 < div class ="form-group " id ="custom-model-group " style ="display: none ">
926- < label for ="custom-model " id ="labelCustomModel "> </ label >
927- < input type ="text " id ="custom-model " />
926+ < label for ="custom-model " id ="labelCustomModel " data-i18n =" model_name " > </ label >
927+ < input type ="text " id ="custom-model " data-i18n-placeholder =" enter_model_name " />
928928 </ div >
929929 < div style ="display: flex; justify-content: flex-end; gap: 12px; margin-top: 24px ">
930- < button type ="button " id ="cancel-settings " style ="background: #e9ecef; color: #495057 "> </ button >
931- < button type ="button " id ="save-settings " class ="btn-primary "> </ button >
930+ < button type ="button " id ="cancel-settings " style ="background: #e9ecef; color: #495057 " data-i18n =" cancel " > </ button >
931+ < button type ="button " id ="save-settings " class ="btn-primary " data-i18n =" save " > </ button >
932932 </ div >
933933 </ div >
934934 </ div >
@@ -937,14 +937,14 @@ <h3 class="settings-title" id="settingsTitle"></h3>
937937 <!-- 左侧面板 -->
938938 < div class ="left-panel ">
939939 < div class ="header ">
940- < h1 id ="headerTitle "> </ h1 >
941- < button class ="settings-btn " id ="open-settings "> </ button >
940+ < h1 id ="headerTitle " data-i18n =" footprint_generator " > </ h1 >
941+ < button class ="settings-btn " id ="open-settings " data-i18n =" settings " > </ button >
942942 </ div >
943943
944944 <!-- 上传区域 -->
945945 < div class ="upload-section ">
946946 < div id ="drop-area " class ="upload-area ">
947- < p id ="uploadText "> </ p >
947+ < p id ="uploadText " data-i18n =" drag_upload " > </ p >
948948 < input type ="file " id ="file-input " multiple accept =".pdf,image/* " style ="display: none " />
949949 </ div >
950950 </ div >
@@ -953,17 +953,17 @@ <h1 id="headerTitle"></h1>
953953 < div class ="controls-section ">
954954 < div class ="control-row single-row ">
955955 < div class ="control-buttons ">
956- < button id ="search-position " class ="btn-primary " disabled > </ button >
957- < button id ="extract-params " class ="btn-success " disabled > </ button >
958- < button id ="clear-selection "> </ button >
959- < button id ="manual-select "> </ button >
960- < button class ="btn-secondary " id ="hideButton "> </ button >
961- < button class ="settings-btn " id ="open-settings-control "> </ button >
956+ < button id ="search-position " class ="btn-primary " disabled data-i18n =" search_footprint_position " > </ button >
957+ < button id ="extract-params " class ="btn-success " disabled data-i18n =" extract_parameters " > </ button >
958+ < button id ="clear-selection " data-i18n =" clear_selection " > </ button >
959+ < button id ="manual-select " data-i18n =" manual_select " > </ button >
960+ < button class ="btn-secondary " id ="hideButton " data-i18n =" hide_window " > </ button >
961+ < button class ="settings-btn " id ="open-settings-control " data-i18n =" settings " > </ button >
962962 </ div >
963- < div class ="timing-display " id ="timing-display "> </ div >
963+ < div class ="timing-display " id ="timing-display " data-i18n =" elapsed_dash " > </ div >
964964 </ div >
965965 < div class ="progress-container ">
966- < div class ="coordinate-display " id ="coordinate-display "> </ div >
966+ < div class ="coordinate-display " id ="coordinate-display " data-i18n =" coordinates_no_selection " > </ div >
967967 < div class ="progress-bar " id ="progress-bar ">
968968 < div class ="progress-fill " id ="progress-fill "> </ div >
969969 </ div >
@@ -974,21 +974,23 @@ <h1 id="headerTitle"></h1>
974974 <!-- 图片显示区域 -->
975975 < div class ="image-display " id ="image-display ">
976976 < div class ="selection-overlay " id ="selection-overlay "> </ div >
977- < div class ="empty-state " id ="emptyState "> </ div >
977+ < div class ="empty-state " id ="emptyState " data-i18n =" upload_prompt " > </ div >
978978 < input type ="file " id ="file-input " multiple accept =".pdf,image/* " style ="display: none " />
979979 </ div >
980980
981981 <!-- 图片导航区域 -->
982982 < div class ="image-navigation " id ="image-navigation " style ="display: none ">
983983 < div class ="nav-controls ">
984- < button id ="prev-image " class ="nav-btn "> </ button >
984+ < button id ="prev-image " class ="nav-btn " data-i18n =" previous_image " > </ button >
985985 < input
986986 type ="number "
987987 id ="page-input "
988988 min ="1 "
989989 value ="1 "
990990 placeholder =""
991991 title =""
992+ data-i18n-placeholder ="page "
993+ data-i18n-title ="page_jump_hint "
992994 style ="
993995 width: 40px;
994996 text-align: center;
@@ -1002,7 +1004,7 @@ <h1 id="headerTitle"></h1>
10021004 "
10031005 />
10041006 / < span id ="total-pages "> 1</ span >
1005- < button id ="next-image " class ="nav-btn "> </ button >
1007+ < button id ="next-image " class ="nav-btn " data-i18n =" next_image " > </ button >
10061008 </ div >
10071009 < div class ="image-info " id ="image-info "> </ div >
10081010 </ div >
@@ -1012,9 +1014,9 @@ <h1 id="headerTitle"></h1>
10121014 < div class ="right-panel ">
10131015 < div class ="pin-table-section ">
10141016 < div class ="table-controls ">
1015- < button id ="add-param "> </ button >
1016- < button id ="clear-table "> </ button >
1017- < button id ="create-footprint " class ="btn-success "> </ button >
1017+ < button id ="add-param " data-i18n =" add_parameter " > </ button >
1018+ < button id ="clear-table " data-i18n =" clear_table " > </ button >
1019+ < button id ="create-footprint " class ="btn-success " data-i18n =" create_footprint " > </ button >
10181020 < select
10191021 id ="package-type-select "
10201022 style ="
@@ -1027,7 +1029,7 @@ <h1 id="headerTitle"></h1>
10271029 margin-left: 8px;
10281030 "
10291031 >
1030- < option value ="" id ="optPackageType "> </ option >
1032+ < option value ="" id ="optPackageType " data-i18n =" package_type " > </ option >
10311033 < option value ="BGA "> BGA</ option >
10321034 < option value ="DIP "> DIP</ option >
10331035 < option value ="QFN "> QFN</ option >
@@ -1040,7 +1042,7 @@ <h1 id="headerTitle"></h1>
10401042 </ div >
10411043 < div class ="pin-table-content ">
10421044 < div id ="pin-table-container ">
1043- < div class ="empty-state " id ="emptyPinState "> </ div >
1045+ < div class ="empty-state " id ="emptyPinState " data-i18n =" no_footprint_params " > </ div >
10441046 </ div >
10451047 </ div >
10461048 </ div >
@@ -1054,6 +1056,18 @@ <h1 id="headerTitle"></h1>
10541056 if ( edaObj && edaObj . sys_I18n ) return edaObj . sys_I18n . text ( tag , undefined , undefined , ...args ) ;
10551057 return tag ;
10561058 }
1059+ function applyI18n ( ) {
1060+ document . querySelectorAll ( '[data-i18n]' ) . forEach ( function ( el ) {
1061+ el . textContent = t ( el . getAttribute ( 'data-i18n' ) ) ;
1062+ } ) ;
1063+ document . querySelectorAll ( '[data-i18n-title]' ) . forEach ( function ( el ) {
1064+ el . setAttribute ( 'title' , t ( el . getAttribute ( 'data-i18n-title' ) ) ) ;
1065+ } ) ;
1066+ document . querySelectorAll ( '[data-i18n-placeholder]' ) . forEach ( function ( el ) {
1067+ el . setAttribute ( 'placeholder' , t ( el . getAttribute ( 'data-i18n-placeholder' ) ) ) ;
1068+ } ) ;
1069+ }
1070+ applyI18n ( ) ;
10571071
10581072 // 设置PDF.js的worker路径
10591073 pdfjsLib . GlobalWorkerOptions . workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js' ;
@@ -1125,67 +1139,67 @@ <h1 id="headerTitle"></h1>
11251139 // 封装类型参数配置
11261140 const packageParams = {
11271141 'BGA' : [
1128- { name : '引脚行数' , key : 'pin_rows' , unit : '' } ,
1129- { name : '引脚列数' , key : 'pin_cols' , unit : '' } ,
1130- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1131- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1132- { name : '引脚直径 (PD)', key : 'pin_diameter' , unit : 'mm' } ,
1133- { name : '引脚间距 (PS)', key : 'pin_spacing' , unit : 'mm' } ,
1134- { name : '引脚纵向间距 (PP)', key : 'pin_pitch' , unit : 'mm' } ,
1142+ { name : t ( 'Pin Rows' ) , key : 'pin_rows' , unit : '' } ,
1143+ { name : t ( 'Pin Columns' ) , key : 'pin_cols' , unit : '' } ,
1144+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1145+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1146+ { name : t ( 'Pin Diameter (PD)') , key : 'pin_diameter' , unit : 'mm' } ,
1147+ { name : t ( 'Pin Spacing (PS)') , key : 'pin_spacing' , unit : 'mm' } ,
1148+ { name : t ( 'Pin Pitch Vertical (PP)') , key : 'pin_pitch' , unit : 'mm' } ,
11351149 ] ,
11361150 'DIP' : [
1137- { name : '引脚数量' , key : 'pin_count' , unit : '' } ,
1138- { name : '引脚跨距' , key : 'LS' , unit : 'mm' } ,
1139- { name : '本体长度' , key : 'BL' , unit : 'mm' } ,
1140- { name : '本体宽度' , key : 'BW' , unit : 'mm' } ,
1141- { name : '引脚直径' , key : 'PD' , unit : 'mm' } ,
1142- { name : '引脚间距' , key : 'PS' , unit : 'mm' } ,
1151+ { name : t ( 'Pin Count' ) , key : 'pin_count' , unit : '' } ,
1152+ { name : t ( 'Lead Span' ) , key : 'LS' , unit : 'mm' } ,
1153+ { name : t ( 'Body Length' ) , key : 'BL' , unit : 'mm' } ,
1154+ { name : t ( 'Body Width' ) , key : 'BW' , unit : 'mm' } ,
1155+ { name : t ( 'Pin Diameter' ) , key : 'PD' , unit : 'mm' } ,
1156+ { name : t ( 'Pin Spacing' ) , key : 'PS' , unit : 'mm' } ,
11431157 ] ,
11441158 'QFN' : [
1145- { name : '引脚数(左右)' , key : 'pin_count_lr' , unit : '' } ,
1146- { name : '引脚数(上下)' , key : 'pin_count_tb' , unit : '' } ,
1147- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1148- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1149- { name : '引脚长度 (PL)', key : 'pin_length' , unit : 'mm' } ,
1150- { name : '引脚宽度 (PW)', key : 'pin_width' , unit : 'mm' } ,
1151- { name : '引脚间距 (PP)', key : 'pin_pitch' , unit : 'mm' } ,
1159+ { name : t ( 'Pin Count (Left/Right)' ) , key : 'pin_count_lr' , unit : '' } ,
1160+ { name : t ( 'Pin Count (Top/Bottom)' ) , key : 'pin_count_tb' , unit : '' } ,
1161+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1162+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1163+ { name : t ( 'Pin Length (PL)') , key : 'pin_length' , unit : 'mm' } ,
1164+ { name : t ( 'Pin Width (PW)') , key : 'pin_width' , unit : 'mm' } ,
1165+ { name : t ( 'Pin Pitch (PP)') , key : 'pin_pitch' , unit : 'mm' } ,
11521166 ] ,
11531167 'QFP' : [
1154- { name : '引脚数(左右)' , key : 'pin_count_lr' , unit : '' } ,
1155- { name : '引脚数(上下)' , key : 'pin_count_tb' , unit : '' } ,
1156- { name : '引脚跨距 (LS1)', key : 'lead_span1' , unit : 'mm' } ,
1157- { name : '引脚纵向跨距 (LS2)', key : 'lead_span2' , unit : 'mm' } ,
1158- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1159- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1160- { name : '引脚长度 (PL)', key : 'pin_length' , unit : 'mm' } ,
1161- { name : '引脚宽度 (PW)', key : 'pin_width' , unit : 'mm' } ,
1162- { name : '引脚间距 (PP)', key : 'pin_pitch' , unit : 'mm' } ,
1168+ { name : t ( 'Pin Count (Left/Right)' ) , key : 'pin_count_lr' , unit : '' } ,
1169+ { name : t ( 'Pin Count (Top/Bottom)' ) , key : 'pin_count_tb' , unit : '' } ,
1170+ { name : t ( 'Lead Span (LS1)') , key : 'lead_span1' , unit : 'mm' } ,
1171+ { name : t ( 'Lead Span Vertical (LS2)') , key : 'lead_span2' , unit : 'mm' } ,
1172+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1173+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1174+ { name : t ( 'Pin Length (PL)') , key : 'pin_length' , unit : 'mm' } ,
1175+ { name : t ( 'Pin Width (PW)') , key : 'pin_width' , unit : 'mm' } ,
1176+ { name : t ( 'Pin Pitch (PP)') , key : 'pin_pitch' , unit : 'mm' } ,
11631177 ] ,
11641178 'SOD' : [
1165- { name : '引脚跨距 (LS)', key : 'lead_span' , unit : 'mm' } ,
1166- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1167- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1168- { name : '引脚长度 (PL)', key : 'pin_length' , unit : 'mm' } ,
1169- { name : '引脚宽度 (PW)', key : 'pin_width' , unit : 'mm' } ,
1179+ { name : t ( 'Lead Span (LS)') , key : 'lead_span' , unit : 'mm' } ,
1180+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1181+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1182+ { name : t ( 'Pin Length (PL)') , key : 'pin_length' , unit : 'mm' } ,
1183+ { name : t ( 'Pin Width (PW)') , key : 'pin_width' , unit : 'mm' } ,
11701184 ] ,
11711185 'SOT23' : [
1172- { name : '引脚数量' , key : 'pin_count' , unit : '' } ,
1173- { name : '引脚跨距 (LS)', key : 'lead_span' , unit : 'mm' } ,
1174- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1175- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1176- { name : '引脚长度 (PL)', key : 'pin_length' , unit : 'mm' } ,
1177- { name : '引脚宽度 (PW)', key : 'pin_width' , unit : 'mm' } ,
1178- { name : '引脚间距 (PP)', key : 'pin_pitch' , unit : 'mm' } ,
1186+ { name : t ( 'Pin Count' ) , key : 'pin_count' , unit : '' } ,
1187+ { name : t ( 'Lead Span (LS)') , key : 'lead_span' , unit : 'mm' } ,
1188+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1189+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1190+ { name : t ( 'Pin Length (PL)') , key : 'pin_length' , unit : 'mm' } ,
1191+ { name : t ( 'Pin Width (PW)') , key : 'pin_width' , unit : 'mm' } ,
1192+ { name : t ( 'Pin Pitch (PP)') , key : 'pin_pitch' , unit : 'mm' } ,
11791193 ] ,
11801194 'SOT223' : [
1181- { name : '引脚数量' , key : 'pin_count' , unit : '' } ,
1182- { name : '引脚跨距 (LS)', key : 'lead_span' , unit : 'mm' } ,
1183- { name : '本体长度 (BL)', key : 'body_length' , unit : 'mm' } ,
1184- { name : '本体宽度 (BW)', key : 'body_width' , unit : 'mm' } ,
1185- { name : '引脚长度 (PL)', key : 'pin_length' , unit : 'mm' } ,
1186- { name : '引脚宽度 (PW)', key : 'pin_width' , unit : 'mm' } ,
1187- { name : '引脚间距 (PS)', key : 'pin_spacing' , unit : 'mm' } ,
1188- { name : '引脚宽度 (PW1)', key : 'pin_width1' , unit : 'mm' } ,
1195+ { name : t ( 'Pin Count' ) , key : 'pin_count' , unit : '' } ,
1196+ { name : t ( 'Lead Span (LS)') , key : 'lead_span' , unit : 'mm' } ,
1197+ { name : t ( 'Body Length (BL)') , key : 'body_length' , unit : 'mm' } ,
1198+ { name : t ( 'Body Width (BW)') , key : 'body_width' , unit : 'mm' } ,
1199+ { name : t ( 'Pin Length (PL)') , key : 'pin_length' , unit : 'mm' } ,
1200+ { name : t ( 'Pin Width (PW)') , key : 'pin_width' , unit : 'mm' } ,
1201+ { name : t ( 'Pin Spacing (PS)') , key : 'pin_spacing' , unit : 'mm' } ,
1202+ { name : t ( 'Pin Width (PW1)') , key : 'pin_width1' , unit : 'mm' } ,
11891203 ] ,
11901204 } ;
11911205
@@ -2869,7 +2883,7 @@ <h1 id="headerTitle"></h1>
28692883 // 验证content是否有效
28702884 if ( ! content || typeof content !== 'string' ) {
28712885 console . error ( 'content为空或不是字符串:' , content ) ;
2872- throw new Error ( 'API返回的内容为空或格式错误' ) ;
2886+ throw new Error ( t ( 'Empty response returned' ) ) ;
28732887 }
28742888
28752889 console . log ( `第 ${ attempt } 次提取结果:` , content ) ;
@@ -2916,8 +2930,8 @@ <h1 id="headerTitle"></h1>
29162930 // 根据提取次数显示不同的成功消息
29172931 const successMessage =
29182932 extractionCount === 1
2919- ? `成功提取 ${ imagesWithSelections . length } 张图片的封装参数(已选择封装类型)`
2920- : `成功提取 ${ imagesWithSelections . length } 张图片的封装参数(智能选择最佳结果)` ;
2933+ ? t ( 'Successfully extracted package parameters from ${1} images (package type selected)' , imagesWithSelections . length )
2934+ : t ( 'Successfully extracted package parameters from ${1} images (intelligent best result)' , imagesWithSelections . length ) ;
29212935 eda . sys_ToastMessage . showMessage ( successMessage , 1 ) ;
29222936 } catch ( error ) {
29232937 console . error ( '提取参数失败:' , error ) ;
@@ -4286,7 +4300,7 @@ <h1 id="headerTitle"></h1>
42864300
42874301 // 检查JSON数据是否包含必要的字段
42884302 if ( ! data || typeof data !== 'object' || ! data . type || ! Array . isArray ( data . pins ) ) {
4289- throw new Error ( 'JSON数据格式不正确,缺少type或pins字段' ) ;
4303+ throw new Error ( t ( 'Invalid JSON data format, missing type or pins field' ) ) ;
42904304 }
42914305
42924306 const type = data . type ;
0 commit comments